* remove deprecated file

* [ACA-1904] Language labels (#879)

* [ACA-2083] reset router cache on login/logout (#867)

* reset router cache on login/logout

* Update src/app/app.routes.strategy.ts

Co-Authored-By: DenysVuika <denys.vuika@gmail.com>

* merge suggestion

* [ACA-2083] reset content filters on logout

* [ACA-2083] unit tests

* [ACA-2067] Side navigation - highlight element with children only when not expanded (#880)

* highlight parent element condition

* update test

* e2e

* add context menu (#881)

* [ACA-2107] upgrade to ADF latest beta (#882)

* [ACA-2107] upgrade ADF to latest beta

* fix adf sidenav class name

* [ACA-2107] update is-selected to adf-is-selected

* [ACA-2107] add 'adf' prefix to classes name

* [ACA-2107] remove ADF duplicate css style

* [ACA-2107] use 'adf-full-width' class

* [ACA-2107] add 'adf' prefix

* [ACA-1928] e2e improvements - part1 (#883)

* refactor Mark as favourite tests
rename method to be more clear
create separate methods for some checks and actions

* forgot some changes

* refactor delete-undo tests

* some more refactoring

* fix

* [ACA-1928] e2e improvements - part2 (#884)

* refactor Mark as favourite tests
rename method to be more clear
create separate methods for some checks and actions

* forgot some changes

* refactor delete-undo tests

* some more refactoring

* fix

* small improvements / refactoring

* upgrade 3rd party dependencies (#886)

* upgrade 3rd party dependencies

* update datepicker

* update code

* remove duplicated strings, use ADF instead (#887)

* extension recommendations

* [ACA-1558] cache busting for index.html (#888)

* use dynamic columns from ADF (#889)

* upgrade to latest ADF 3.0.0 alpha

* migrate to ADF column components

* use dynamic column from ADF

* fix e2e tests

* [ACA-2122] automatic code formatting on commit (#890)

* [ACA-2120] update library toolbar (#891)

* [ACA-2131] fix leave library icon for context menu

* remove moment-es6 usage (#892)

* [ACA] Create Library - switch to ADF component (#893)

* use adf component

* fix component name locator

* update extension registration docs

* fix SSO defaults

* fix pre-commit issue with partial commits

* [ACA-2116] search results available actions (#895)

* add item.id to File Libraries

* add method to wait for node to be indexed

* create separate methods in queries API to wait for sites or wait for nodes

* improvements, renaming

* renaming

* fix

* add tests for actions on search results

* add wait and use new method

* fix

* another fix

* use correct method

* more fixes

* create method for clickView button

* fixes

* no message

* unified format for viewer sub-menus (#901)

* unified format for viewer sub-menus

* fix tests

* update prettier

* [ACA-2157] Added basic ABN metadata (#902)

* upgrade to latest JS-API and ADF (#896)

* improved update script and latest ADF libs

* upgrade to latest js-api and ADF

* upgrade tests

* update viewer code

* use @alfresco/js-api

* update to latest adf

* fix deprecation issues

* update viewer

* fix copy/move dialog

* change expect

* fix remove site from favorites

* fix unit test

* update adf version

* use ADF upload dialog

* [ACA-820] add tests for Copy content (#899)

* add tests for Copy content

* fix

* forgot some ids

* update expected favorites number

* support for SSO settings (#905)

* [ACA-2157] Fixed structure, markup and links (#904)

* [ACA-2157] Added brief description and updated links

* [ACA-2157] Fixed broken image URL

* [ADF-2157] Added YAML index file for ABN (#903)

* [e2e] new reporter (#906)

* try new reporter

* run specific suite for testing purposes

* change folder output for report

* more report settings

* remove fdescribe

* remove package and update package-lock

* remove disabled tests not needed by the new reporter

* try to identify cause of travis failure

* run only specific tests for investigation purpose

* remove sleep and increase retry delay

* try a different fix

* revert to previous fix

* try different expects

* call different js-api method

* remove parameter not needed anymore

* upgrade dependencies (#907)

* add tests for Move content (#908)

* [ACA-213] Edit Offline (#909)

* WRITE_LOCK evaluator

* evaluate actions for WRITE_LOCK

* edit offline action

* DL icon for WRITE_LOCK files

* edit offline directive

* custom name column

* localisation

* toggle offline edit extension

* move takeUntil operator

* add tooltip

* better selector to differentiate Edit folder from Edit Offline

* default to empty object for null properties object

* isPersonalFiles evaluator

* isLibraryFiles evaluator

* isLibraryFiles evaluator

* isPersonalFiles evaluator

* update canEditLockedFile rule

* upgrade libraries (#910)

* upgrade libraries

* fix breaking changes

* fix divider

* remove header workarounds

* update repository to 6.1.2-ga, SSO example (#914)

* remove old compose, update to 6.1.2-ga

* SSO with vanilla keycloak

* [ACA-2162] allow custom icons with navbar (#917)

* allow custom icons with navbar

* fix breaking change

* update protractor settings

* pin typescript version, regenerate lock file

* [ACA-2168] auto-generate licenses for docker image (#918)

* auto-generate licenses for docker image

* update version label

* make app agnostic

* [ACA-213] Edit Offline - permissions (#911)

* edit offline action rules

* unlock node error message

* update extensions rules

* lock unlock evaluators

* LockNodeDirective over EditOfflineDirective

* disable tests failing cause of unrelated bug

* isUserWriteLockOwner over isUserWriteLock

* fix lock icon for retina displays

* [ACA-2164] Node version action (#916)

* export upload effects and actions

* remove node version effect and action

* remove node version theme

* change old version manager implementation

* get node info from store selection

* upload version dialog container

* node version form

* update app module

* upload version effect and action

* update version action

* internationalization

* refresh on upload version

* remove old implementation tests

* remove adf-version-manager dialog implementation

* revert adf version component

* fix viewer version action

* [ACA-2160] add tests for Edit offline actions availability (#921)

* add tests for Edit offline actions availability

* fix delete / undo delete tests

* Keensoft AOS extension (#920)

* aos extension

* update karma

* lint improvements and fixes

* update script

* update scripts

* update scripts

* reduce about 56.4 kB of polyfills for modern browsers

* deficated aosHost value to have AOS on separate servers

* context menu and toolbar

* visibility evaluator

* code improvements and fixes

* support locking, lock checks

* [ACA-2193] Lock node - unlock after new version is uploaded (#924)

* unlock node api call

* unlock action and effect

* unlock node after version upload

* check if locked

* clear version input on dialog cancel event

* update viewer on node version upload

* update viewer on file upload delete

* test

* update tests

* update tests

* rename evaluators

* update docs

* minor script improvements

* update AOS extension docs and version

* update package configuration for AOS ext

* update AOS extension details

* Search on mobile opens Sidemenu (#929)

* Added a check for mobile pages to prevent sidemenu opening

* [ACA-2200] Upgrade to 3.0.0-beta9 ADF (#931)

* upgrade to latest ADF 3.0.0-alpha

- remove selectedFacetQueries check
- renamed hasPermission from ADF ContentService to hasAllowableOperations

* update to ADF 3.0.0-beta9

* [ACA-2200] mincount workaround

- until we get the fix for the facet update issue (ADF-3401)

* [ACA-2171] enable copy and move to library tests (#933)

* [ACA-2198 ACA-2206]  Node version - align dialog with XD (#937)

* make comment field not required

* make Minor default version option

* tests

* fix form version options label

* test form state on initialization

* [ACA-2210] Version Dialog - update button text (#939)

* dialog action buttons text to uppercase

* dialog text Cancel over Close

* update translation reference

* [ACA-213] Upload Version - version options use boolean values (#940)

* version form data interface

* subscribe value data type

* use form data  boolean value

* update tests

* [ACA-2208] Hide app menu on swipe (#934)

* mobile: hide app menu on swipe left

* check for mobile screen size

* space for click out on small devices

* added test

* fix test

* [ACA-2199] Upload Version - granular permission   (#938)

* canUploadVersion evaluator

* change upload version action rule

* update docs

* simplify condition

* unit tests and code fixes

* [ACA-2211] auth guard: add support for withCredentials (#942)

* auth guard: add support for withCredentials

* formatting fixes

* remove fdescribe

* [ACA-2204] Upgrade to ADF 3.0.0 release (#949)

* upgrade to ADF 3.0.0

* update unit tests

* disable versioning tab in info drawer (#941)

* [ACA-213] Version Dialog - tests (#948)

* enable Esc action to close dialog

* version dialog form tests

* test fix

* [ACA-2193] Upload new content version - unsubscribe upload event (#925)

* remove console log

* unsubscribe upload event after new version

* unit tests

* update AOS extension to ADF 3.0.0

* Upgrade libs (#952)

* update libs

* remove i18n workaround

* node locking  enhancements and fixes (#955)

* optimize image resolver

* allow previewing locked files

* allow selecting locked nodes

* fix comments and metadata tabs

* improved lock checks

* remove obsolete "experimental" directive

* [ACA-2177] Actions - rearrange actions order  (#922)

* rearange actions

* remove separator duplication

* don't show last divider element

* update e2e

* update e2e

* Update toolbar-single-selection.test.ts

remove fdescribe

* move comment as well

* edit folder locator

* edit folder action

* edit folder action from toolbar more menu

* edit folder context menu id

* dont render versions tab

* [ACA-2199] fix Upload New Version action availability (#959)

* fix Upload New Version action availability

* update unit tests

* remove workaround

* add catch for tests failing on Bamboo

* add new line

* add tests for Upload New Version (#960)

* remove separator between Favorite and Edit folder (#963)

* [ACA-2221] Lock node - check selection is not null (#966)

* check selection is not null

* test

* add tests for downloading a single file (#967)

* [ACA-833] automate tests for download as zip (#968)

* add tests for downloading a single file

* automate tests for download as zip

* [ACA-2216] Shared link preview - use extension actions (#964)

* isSharedFileViewer evaluator

* navigation evaluators tests

* update docs

* fallback for SharedLink entry

* shared link view use extensions

* rules for link shared view actions

* dedicated extension definition for shared link action toolbar

* resolve selection and actions

* update tests

* remove un used imports

* nest shared link viewer toolbar actions in to viewer structure

* [ACA-2180] Viewer toolbar - rearrange actions layout (#962)

* merge action in toolbar submenu

* viewer add info drawer action

* toggle infoDrawer extension action

* hide viewer toolbar info drawer action

* fix typo

* allow to  unsubscribe from infoDrawerOpened event

* [ACA-2207] Upload Dialog - restore previous version on delete (#951)

* restore version over delete node

* apply prettier

* clean up unnecessary dependencies

* remove style file

* set CANCEL status on on deleted node version instances

* Update upload.module.ts

remove extra licence text

* fix typo

* remove duplicate strings

* [ACA-2212] allow "edit in office" only for basic auth (#971)

* allow AOS only for basic auth for now

* bump aos extension version

* [ACA-2208] Hide app menu on swipe (#970)

* [ACA-2220] simple "search in fields" support (#972)

* simple "search in fields" support

* unit tests

* add separator (#974)

* [ACA-2222] add e2e tests for pagination on Favorite Libraries (#969)

* add tests for pagination on Favorite Libraries

* add TestRail ids
add tests for pagination for empty page and single page

* Delete package-lock.json

* Revert "Delete package-lock.json"

This reverts commit 41eba0c57532373d87d454372273b54ba00e880a.

* restore package-lock

* [ACA-2219] support more precise searching (#976)

* support more precise searching

* exact term matching

* remove fdescribe

* update docs

* [ACA-1259] automate remaining tests for sidebar (#977)

* automate remaining tests for sidebar

* formatting

* reload active doclist via NgRx actions (#978)

* doclist reload action and effect

* deprecate folderEdited event

* deprecate "favoriteToggle" event

* deprecate "favoriteRemoved" event

* update docs

* unified reload function

* deprecate "nodesRestored" event

* deprecate "nodesPurged" event

* test fixes

* deprecate "nodesMoved" event

* reduce the use of "nodesDeleted"

* [ACA-2229] run aca nginx as non-root (#979)

* run aca nginx as non-root

* remove edit permissions from html folder

* [ACA-2229] docker security fixes (#980)

* docker permission fixes

* remove index.html edit permissions

* support repository info with app state (#984)

* [ACA-2214] Sharing URL being constructed from ECM Host incorrectly (#981)

* fix baseShareUrl defaults

* allow controlling full path

* unit test

* update tomcat settings

* use single slash

* simplify documentation

* [ACA-2194] better custom aspects in metadata tab (#985)

* better custom aspects in metadata tab

* update test

* fix lockby position (#986)

* compatibility matrix (#989)

* [ACA-2228] Add PipeModule to AppTestingModule (#993)

- fixes unit tests after upgrade to 3.1.0-beta4

* responsive breadcrumb (#990)

* [ACA-2239] initial localisation support for AOS extension (#988)

* setup i18n for aos extension

* translate action names, generic icon

* unit tests and bug fixes

* use AOS testing with CI

* [ACA-2242] add old style back (#994)

fixes missing buttons styles issue until ADF 3.1.0 will fix it

* upgrade libs to latest versions (#996)

* Windows compatibility

* [ACA-2195] fix redirect on login after page reload (#997)

* fix build script for Windows

* update evaluator docs, workspace snippet (#995)

* add missing docs and code hints

* update app evaluator docs and code hints

* fix route url special characters (#1000)

* revert change for AOS related to lock owners

* [ACA-2215] toggle search filter (#998)

* support for toggling search filter

* update docs

* disable e2e test

* update e2e

* [ACA-2133] fix application ready event for kerberos (#1002)

* fix application ready event for kerberos

* format file

* spellcheck fixes

* hide AOS when in trashcan

* fix broken test

* [ACA] Search - show error message on error (#1003)

* show error message

* remove fdescribe

* add documentation on SSO, minor docs fixes (#1005)

* menu filter disabled items (#1009)

* 1.7.0

* [ACA-2261] improve UX on search input (#1004)

* Remove search on change

- search call would be triggered only on submit or on option change

* clicking search icon triggers search

* caches user changes for a possible future search

* caches non-empty user changes for a possible future search

* close search options menu on submit

* update queryBuilder and navigate to new search url

* add setting to enable/disable searching after typing on search input

* fix double search call

* Apply suggestions from code review

- custom name to distinguish between ADF and ACA settings

Co-Authored-By: suzanadirla <dirla.silvia.suzana@gmail.com>

* [ACA-2264] fix loading on search (#1011)

- do nothing on null built query

* readme update

* update readme

* [ACA-1627] add automated tests for Comments (#1012)

* bump runtime version for core extension

* json schema fixes

* [ACA-2260] Open in Office - action breaks application in IE (#1014)

* ie office luncher workaround

* open office without location navigation

* check instance before remove

* various bug fixes (#1010)

* various bug fixes

* use 'remove favorite' label where appropriate

* fix toggle favorite component labels

* e2e type check and fixes

* favorite library label

* support toggle favorite component selectors

* update tests

* update e2e tests

* update e2e

* e2e update

* update e2e

* [ACA-2259] Edit in Microsoft Office - check update permissions (#1015)

* [ACA-2259] Edit in Microsoft Office - check update permissions

* [ACA-2259] check update permissions - unit tests

* [ACA-2259] refactor - check allowableOperationsOnTarget from service

* [ACA-2259] add back check only on target for SharedFiles

* [ACA-2259] SharedLinks are not folders

* type-safe api for node permissions

* workaround for shared files

* use hasOwnProperty function

* fix visibility evaluation for create menu (#1017)

* [ACA-2270] allow add comments on folder (#1018)

* [ACA-2270] allow add comments on folder

* [ACA-2270] fix return on else

* [ACA-2270] add unit tests

* update translations (#1023)

* assert file extension validity first (#1025)

* hide empty metadata by default (#1024)

* update copyright year (#1022)

* update copyright year

* forgot a file

* update year on licence header

* extensions flag inside settings page

* support "disabled" rules for Viewer extensions

* set relevance descending by default (#1027)

* [ACA-2284] Shared Link - Error when trying to download a shared file (#1026)

* shared link content download action

* use same action and effect

* call appropriate api baes on location

* remove unused property

* remove unneeded divider from toolbar (#1028)

* use LTS node.js (#1031)

* Update README.md (#1032)

* Update README.md

* Update README.md

* Update introduction-to-extending.md

* Update search-results.md (#1034)

* Update document-list-layout.md (#1035)

* Update README.md (#1033)

* Update README.md (#1036)

* [ACA-2299] fix search error translation (#1030)

* fix search error translation

* fix translation fallback

* remove fdescribe
This commit is contained in:
Denys Vuika 2019-03-22 14:51:40 +00:00 committed by GitHub
parent 95f19c3dc6
commit c8b99b9d29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
562 changed files with 29670 additions and 22477 deletions

1
.gitignore vendored
View File

@ -23,6 +23,7 @@
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets
.history
# misc

View File

@ -6,7 +6,7 @@ addons:
chrome: stable
language: node_js
node_js:
- '8'
- '10'
before_script:
- sudo /etc/init.d/postgresql stop
before_install:
@ -20,8 +20,6 @@ jobs:
name: 'Code quality checks'
script:
- npm run lint
- npm run spellcheck
- npm run format:check
- stage: test
name: 'Unit tests'
script:

12
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"recommendations": [
"eg2.tslint",
"angular.ng-template",
"streetsidesoftware.code-spell-checker",
"peterjausovec.vscode-docker",
"editorconfig.editorconfig",
"davidanson.vscode-markdownlint",
"esbenp.prettier-vscode",
"eamodio.gitlens"
]
}

View File

@ -6,5 +6,8 @@
"editor.formatOnSave": true,
"[json]": {
"editor.formatOnSave": false
},
"markdownlint.config": {
"MD033": false
}
}

19
.vscode/typescript.code-snippets vendored Normal file
View File

@ -0,0 +1,19 @@
{
"ext-evaluator": {
"description": "Generate a new evaluator.",
"scope": "typescript",
"prefix": "ext-evaluator",
"body": [
"/**",
" * Checks if ${2:<description>}.",
" * JSON ref: `app.$1`",
" */",
"export function ${1:name}(",
"\tcontext: AppRuleContext,",
"\t...args: RuleParameter[]",
"): boolean {",
"\treturn ${3:true};${0}",
"}"
]
}
}

View File

@ -1,13 +1,40 @@
# 1. Generate licenses
FROM node:11.9-alpine AS builder
WORKDIR /usr/src/alfresco
COPY package.json package.json
RUN mkdir -p ./licenses && \
yarn licenses list > ./licenses/licenses.txt && \
yarn licenses generate-disclaimer > ./licenses/disclaimer.txt
# 2. Generate image
FROM nginx:stable-alpine
LABEL version="1.4"
LABEL version="1.7"
LABEL maintainer="Denys Vuika <denys.vuika@alfresco.com>"
COPY nginx.conf /etc/nginx/nginx.conf
ARG GROUPNAME=Alfresco
ARG GROUPID=1000
ARG USERNAME=aca
ARG USERID=33009
COPY ./docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh
COPY ./docker/nginx.conf /etc/nginx/nginx.conf
COPY ./docker/entrypoint.sh /
WORKDIR /usr/share/nginx/html
COPY dist/app/ .
COPY --from=builder /usr/src/alfresco/licenses ./licenses
ENTRYPOINT [ "/docker-entrypoint.sh" ]
RUN addgroup -g ${GROUPID} ${GROUPNAME} && \
adduser -S -u ${USERID} -G ${GROUPNAME} -s "/bin/bash" ${USERNAME} && \
chown -R ${USERNAME}:${GROUPNAME} ./app.config.json && \
chown -R ${USERNAME}:${GROUPNAME} /var/cache/nginx && \
touch /var/run/nginx.pid && \
chown -R ${USERNAME}:${GROUPNAME} /var/run/nginx.pid && \
chmod +x /entrypoint.sh && \
chown -R ${USERNAME}:${GROUPNAME} /entrypoint.sh
EXPOSE 8080
USER ${USERNAME}
ENTRYPOINT [ "/entrypoint.sh" ]

127
README.md
View File

@ -1,5 +1,5 @@
<p align="left"> <img title="Alfresco" src="alfresco.png" alt="Alfresco - make business flow"></p>
<p align="left"> <img title="Alfresco" src="alfresco.png" alt="Alfresco - make business flow"></p>
# Alfresco Content Application
Testing Supported By<br/>
@ -7,74 +7,97 @@ Testing Supported By<br/>
## Introduction
The Alfresco Content Application a file management application built using
[Alfresco Application Development Framework (ADF)](https://github.com/Alfresco/alfresco-ng2-components) components and was generated with [Angular CLI](https://github.com/angular/angular-cli).
The Alfresco Content Application a content management application built using
[Alfresco Application Development Framework (ADF)](https://github.com/Alfresco/alfresco-ng2-components) components
and was generated with [Angular CLI](https://github.com/angular/angular-cli).
### Who is this application for
The Content Application is a streamlined experience for end users on top of Alfresco Content Services, focused on file management within the content repository. It provides developers with an easily extendable environment for lightening fast custom application development by providing safe ways to inject custom controls, viewer components, pages and plug-ins without upgrade concerns.
The Content Application is a streamlined experience for end users on top of Alfresco Content Services, focused on file management within the Alfresco content repository. It provides developers with an easily extendable environment for lightening fast custom application development by providing safe ways to inject custom controls, viewer components, pages and plug-ins without upgrade concerns.
### Where to get help
There are a number of resources available to help get you started with the Content App and the ADF:
* [Content App Documentation](https://alfresco.github.io/alfresco-content-app/)
* [Alfresco ADF Documentation](https://alfresco.github.io/adf-component-catalog/)
* [Alfresco Community](https://community.alfresco.com/)
To get help on Angular CLI use ng help or read the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
There are a number of resources available to help get you started with the Content App and the ADF:
- [Gitter Chat](https://gitter.im/Alfresco/content-app) - Developer community chat
- [Content App Documentation](https://alfresco-content-app.netlify.com/) - Developer documentation
- [Alfresco ADF Documentation](https://www.alfresco.com/abn/adf/) - Application Development Framework documentation
- [Alfresco Community Portal](https://community.alfresco.com/) - Developer Communinty Forums
- [Alfresco Customer Support](https://support.alfresco.com/) - Customer support for the Alfresco Digital Workspace
### Raising issues and feature requests
Isuses can be raised in GitHub or in the Alfresco JIRA project.
Issues can be raised in [GitHub] or in the Alfresco JIRA project.
Please include a clear description, steps to reproduce and screenshots where appropriate.All issues will be reviewed; bugs will be categorized if reproducible and enhancement/feature suggestions will be considered against existing priorities if the use case serves a general-purpose need.
#### Features added in the latest release
* Library Management
* For end users: Join and favorite libraries
* New search input to find Libraries, files and/or folders
* Updated action toolbar, right click context menu and refresh of some icons
Please refer to the [release notes](https://github.com/Alfresco/alfresco-content-app/releases) for details of all changes.
- Edit Offline - lock and download files whilst editing
- Edit Online - edit files directly in Microsoft Office
- [Alfresco Full Text Search (FTS) syntax](https://alfresco-content-app.netlify.com/#/features/search-results?id=alfresco-full-text-search) - enhanced search input to support the Alfresco Search Query Language
- [Single Sign-On](https://alfresco-content-app.netlify.com/#/getting-started/sso) (SSO) support with Alfresco Identity Service and ADF 3.0.0, basic Kerberos support
Please refer to the [release notes] for details of all changes.
#### High level feature themes planned for 2019
* Collaboration & File Management
* Edit offline, and edit online with Alfresco Office Services (AOS)
* Folder rule creation
* File/Folder linking via secondary association
* File Library Management
* For managers: Create libraries, manage users and requests to join
* Single Sign On
* Support for Alfresco Identity Service
* Enhanced UI and user experiance
* Search result facet improvements
* Search query input assistance
* Metadata information drawer enhancements
### Want to help?
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our guidelines for [contributing](https://github.com/Alfresco/alfresco-content-app/blob/master/CONTRIBUTING.md) and then check out one of our issues in the [Jira](https://issues.alfresco.com/jira/projects/ACA) or [GitHub](https://github.com/Alfresco/alfresco-content-app/issues)
- Extensibility
- Building on the existing framework to futher enhance the developer experiance
- Collaboration & File Management
- Folder rule creation
- File/Folder linking via secondary association
- File Library Management
- For managers: manage Libtrary users and requests to join
- Enhanced UI and user experience
- New language translations (Arabic, Czech, Danish, Finnish, Polish and Swedish).
- Accessibility WCAG AA complaince
- Search result facet improvements
- Search query input assistance
- Metadata information drawer enhancements
### Want to help
Want to file a bug, contribute some code, or improve documentation? Excellent!
Read up on our guidelines for [contributing] and then check out one of our issues in the [Jira] or [GitHub].
## Compatibility
| ACA Version | Built with | Tested on |
| ----------- | ---------- | --------- |
| ACA 1.7 | ADF 3.0.0 | ACS 6.1 |
| ACA 1.6 | ADF 2.6.1 | ACS 6.1 |
| ACA 1.5 | ADF 2.6.0 | ACS 6.0 |
| ACA 1.4 | ADF 2.5.0 | ACS 6.0 |
| ACA 1.3 | ADF 2.4.0 | ACS 6.0 |
| ACA 1.2 | ADF 2.3.0 | ACS 5.2 |
| ACA 1.1 | ADF 2.2.0 | ACS 5.2 |
| ACA 1.0 | ADF 2.0.0 | ACS 5.2 |
## Available Features
| Feature | Description |
|------------------|----------------------------------------------------------------|
| My Files | Folder/File browsing of Personal Files.|
| File Libraries | Create, find, join and browse the file libraries of sites created in the repository.|
| Shared Files | Lists all files that have shared. |
| Recent Files | List files created and/or modified by the logged users within the last 30 days.|
| Favorites | Lists all favorited files for the user. |
| Trash | Lists all deleted items stored in the trash can, users can restore or permanently remove. Admin user will see items deleted by all users.|
| Upload | Files and folders can be uploaded through the New button or by dragging and dropping into the browser.|
| Search | Quick search with live results, and full faceted search results page.|
| Actions | A number of actions can be performed on files and/or folders, either individually or multiples at a time.|
| Viewer | Viewing files in natively in the browser, unsupported formats are transformed by the repository. |
| Metadata | The information drawer can be configured in the app.config.json to display metadata information, by default file the Properties Aspect is shown and images will also include EXIF information.|
| File Sharing | Share files, with time expiry if required, externally with uniquely generated URLs.|
| Versioning | The version manager provides access and management of previous file versions, and the ability to upload new versions.|
| Permissions | Granular user permission management of the folders and files throughout the repository.|
| Extensibility | The application provides safe extension points allowing full customiation; see [Documentation](https://alfresco.github.io/alfresco-content-app/#/extending) for details. |
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
| Version | Feature | Description |
| ------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1.5 | My Files | Folder/File browsing of Personal Files. |
| 1.5 | File Libraries | Create, find, join and browse the file libraries of sites created in the repository. |
| 1.5 | Shared Files | Lists all files that have shared. |
| 1.5 | Recent Files | List files created and/or modified by the logged users within the last 30 days. |
| 1.5 | Favorites | Lists all favorite files for the user. |
| 1.5 | Trash | Lists all deleted items stored in the trash can, users can restore or permanently remove. Admin user will see items deleted by all users. |
| 1.5 | Upload | Files and folders can be uploaded through the New button or by dragging and dropping into the browser. |
| 1.5 | Search | Quick search with live results, and full faceted search results page. |
| 1.5 | Actions | A number of actions can be performed on files and/or folders, either individually or multiples at a time. |
| 1.5 | Viewer | Viewing files in natively in the browser, unsupported formats are transformed by the repository. |
| 1.5 | Metadata | The information drawer can be configured in the app.config.json to display metadata information, by default file the Properties Aspect is shown and images will also include EXIF information. |
| 1.5 | File Sharing | Share files, with time expiry if required, externally with uniquely generated URLs. |
| 1.5 | Versioning | The version manager provides access and management of previous file versions, and the ability to upload new versions. |
| 1.5 | Permissions | Granular user permission management of the folders and files throughout the repository. |
| 1.5 | Extensibility | The application provides safe extension points allowing full customisation; see [Documentation](https://alfresco-content-app.netlify.com/#/extending/) for details. |
| 1.6 | Library management | Join and favorite libraries. New search input to find Libraries, files and/or folders. |
| 1.7 | Edit Offline | Lock and unlock for editing, download current version, upload new version. |
| 1.7 | Edit with Microsoft Office | Extension to edit online with Alfresco Office Services (AOS) |
| 1.7 | Single Sign-On (SSO) | Support for Alfresco Identity Service, with ADF 3.0.0 |
| 1.7 | Search Query Language | Enhanced search input using the Alfresco Search Query Language |
[contributing]: https://github.com/Alfresco/alfresco-content-app/blob/master/CONTRIBUTING.md
[github]: https://github.com/Alfresco/alfresco-content-app/issues
[jira]: https://issues.alfresco.com/jira/projects/ACA
[release notes]: https://github.com/Alfresco/alfresco-content-app/releases

View File

@ -45,15 +45,30 @@
"input": "node_modules/pdfjs-dist/build",
"output": "/"
},
{
"glob": "**/*.json",
"input": "node_modules/@denysvuika/aca-dev-tools/assets",
"output": "./assets/plugins"
},
{
"glob": "extension.schema.json",
"input": ".",
"output": "./assets"
},
{
"glob": "**/*",
"input": "node_modules/@alfresco/adf-office-services-ext/assets",
"output": "./assets/adf-office-services-ext"
},
{
"glob": "**/*",
"input": "projects/adf-office-services-ext/assets",
"output": "./assets/adf-office-services-ext"
},
{
"glob": "aos.plugin.json",
"input": "node_modules/@alfresco/adf-office-services-ext/assets",
"output": "./assets/plugins"
},
{
"glob": "aos.plugin.json",
"input": "projects/adf-office-services-ext/assets",
"output": "./assets/plugins"
}
],
"styles": [
@ -62,10 +77,11 @@
"src/styles.scss"
],
"scripts": [
"node_modules/pdfjs-dist/build/pdf.js",
"node_modules/pdfjs-dist/web/pdf_viewer.js",
"node_modules/moment/min/moment.min.js"
]
"node_modules/pdfjs-dist/build/pdf.js",
"node_modules/pdfjs-dist/web/pdf_viewer.js",
"node_modules/moment/min/moment.min.js"
],
"es5BrowserSupport": true
},
"configurations": {
"production": {
@ -222,6 +238,41 @@
}
}
}
},
"adf-office-services-ext": {
"root": "projects/adf-office-services-ext",
"sourceRoot": "projects/adf-office-services-ext/src",
"projectType": "library",
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-ng-packagr:build",
"options": {
"tsConfig": "projects/adf-office-services-ext/tsconfig.lib.json",
"project": "projects/adf-office-services-ext/ng-package.json"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/adf-office-services-ext/src/test.ts",
"tsConfig": "projects/adf-office-services-ext/tsconfig.spec.json",
"karmaConfig": "projects/adf-office-services-ext/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/adf-office-services-ext/tsconfig.lib.json",
"projects/adf-office-services-ext/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "app",

View File

@ -3,7 +3,7 @@ npm run build.e2e -- --base-href ./
node -e "
const fs = require('fs');
const config = require('./dist/app/app.config.json');
config.baseShareUrl = 'http://localhost:4000/content-app';
config.baseShareUrl = 'http://localhost:4000/content-app/#/preview/s/';
fs.writeFileSync(
'./dist/app/app.config.json',
JSON.stringify(config, null, 2)

View File

@ -2,11 +2,17 @@
"version": "0.1",
"language": "en",
"words": [
"Kerberos",
"succes",
"sharedlinks",
"Redistributable",
"fullscreen",
"LGPL",
"Browserstack",
"mincount",
"QNAME",
"PNAME",
"mimetype",
"ngrx",
"ngstack",
@ -56,8 +62,7 @@
"keycodes",
"denysvuika",
"submenu",
"submenus",
"simpletask"
"submenus"
],
"dictionaries": ["html", "en-gb", "en_US"]
}

146
docker-compose-keycloak.yml Normal file
View File

@ -0,0 +1,146 @@
version: '2'
services:
alfresco:
image: alfresco/alfresco-content-repository-community:6.1.2-ga
mem_limit: 1500m
depends_on:
- postgres
- auth
environment:
AUTH_SERVER_URL: ${AUTH_SERVER_URL}
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
-Dalfresco.port=8080
-Daos.baseUrlOverwrite=http://localhost:8080/alfresco/aos
-Dmessaging.broker.url="failover:(nio://activemq:61616)?timeout=3000&jms.useCompression=true"
-Ddeployment.method=DOCKER_COMPOSE
-Dcsrf.filter.enabled=false
-Xms1g -Xmx1g
-Dauthentication.chain=identity-service1:identity-service,alfrescoNtlm1:alfrescoNtlm
-Didentity-service.enable-basic-auth=true
-Didentity-service.authentication.validation.failure.silent=false
-Didentity-service.auth-server-url=${AUTH_SERVER_URL}
-Didentity-service.realm=alfresco
-Didentity-service.resource=alfresco
'
networks:
- internal
ports:
- 8080:8080 #Browser port
share:
image: alfresco/alfresco-share:6.1.0-RC3
mem_limit: 1g
depends_on:
- alfresco
environment:
- REPO_HOST=alfresco
- REPO_PORT=8080
- 'CATALINA_OPTS= -Xms500m -Xmx500m'
networks:
- internal
ports:
- 8083:8080
postgres:
image: postgres:10.1
mem_limit: 1500m
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.3.0-RC2
mem_limit: 2500m
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
- 'SOLR_JAVA_MEM=-Xms2g -Xmx2g'
networks:
- internal
ports:
- 8983:8983 #Browser port
activemq:
image: alfresco/alfresco-activemq:5.15.6
mem_limit: 2048m
networks:
- internal
ports:
- 8161:8161 # Web Console
- 5672:5672 # AMQP
- 61616:61616 # OpenWire
- 61613:61613 # STOMP
content-app:
image: alfresco/alfresco-content-app:latest
build: .
environment:
# BASEPATH: ./
APP_CONFIG_OAUTH2_HOST: ${APP_CONFIG_OAUTH2_HOST}
APP_CONFIG_AUTH_TYPE: ${APP_CONFIG_AUTH_TYPE}
APP_CONFIG_OAUTH2_CLIENTID: ${APP_CONFIG_OAUTH2_CLIENTID}
APP_CONFIG_OAUTH2_REDIRECT_SILENT_IFRAME_URI: ${APP_CONFIG_OAUTH2_REDIRECT_SILENT_IFRAME_URI}
APP_CONFIG_OAUTH2_REDIRECT_LOGIN: ${APP_CONFIG_OAUTH2_REDIRECT_LOGIN}
APP_CONFIG_OAUTH2_REDIRECT_LOGOUT: ${APP_CONFIG_OAUTH2_REDIRECT_LOGOUT}
depends_on:
- alfresco
networks:
- internal
ports:
- 4001:80
# volumes:
# - ./app.config.json:/usr/share/nginx/html/app.config.json
# - ./nginx.conf:/etc/nginx/conf.d/default.conf
proxy:
image: nginx:stable-alpine
depends_on:
- content-app
volumes:
- ./docker/proxy/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- internal
ports:
- 4000:80
auth:
image: jboss/keycloak:4.8.3.Final
volumes:
- ./docker/auth/alfresco-realm.json:/tmp/alfresco-realm.json
environment:
- KEYCLOAK_USER=admin
- KEYCLOAK_PASSWORD=admin
- KEYCLOAK_IMPORT=/tmp/alfresco-realm.json
- DB_VENDOR=h2
networks:
- internal
ports:
- 8085:8080
networks:
internal:

View File

@ -1,8 +1,9 @@
version: '3'
version: '2'
services:
alfresco:
image: alfresco/alfresco-content-repository-community:6.1.0-ea
image: alfresco/alfresco-content-repository-community:6.1.2-ga
mem_limit: 1500m
depends_on:
- postgres
environment:
@ -17,8 +18,12 @@ services:
-Dsolr.base.url=/solr
-Dindex.subsystem.name=solr6
-Dshare.host=localhost
-Dalfresco.port=8080
-Daos.baseUrlOverwrite=http://localhost:8080/alfresco/aos
-Dmessaging.broker.url="failover:(nio://activemq:61616)?timeout=3000&jms.useCompression=true"
-Ddeployment.method=DOCKER_COMPOSE
-Dcsrf.filter.enabled=false
-Xms1g -Xmx1g
'
networks:
- internal
@ -26,12 +31,14 @@ services:
- 8080:8080 #Browser port
share:
image: alfresco/alfresco-share:6.0.c
image: alfresco/alfresco-share:6.1.0-RC3
mem_limit: 1g
depends_on:
- alfresco
environment:
- REPO_HOST=alfresco
- REPO_PORT=8080
- 'CATALINA_OPTS= -Xms500m -Xmx500m'
networks:
- internal
ports:
@ -39,6 +46,7 @@ services:
postgres:
image: postgres:10.1
mem_limit: 1500m
environment:
- POSTGRES_PASSWORD=alfresco
- POSTGRES_USER=alfresco
@ -50,7 +58,8 @@ services:
- 5432:5432
solr6:
image: alfresco/alfresco-search-services:1.2.0
image: alfresco/alfresco-search-services:1.3.0-RC2
mem_limit: 2500m
depends_on:
- alfresco
environment:
@ -62,6 +71,7 @@ services:
- SOLR_SOLR_PORT=8983
#Create the default alfresco and archive cores
- SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive
- 'SOLR_JAVA_MEM=-Xms2g -Xmx2g'
networks:
- internal
ports:
@ -69,6 +79,7 @@ services:
activemq:
image: alfresco/alfresco-activemq:5.15.6
mem_limit: 2048m
networks:
- internal
ports:
@ -85,7 +96,7 @@ services:
networks:
- internal
ports:
- 4001:80
- 4001:8080
# volumes:
# - ./app.config.json:/usr/share/nginx/html/app.config.json
# - ./nginx.conf:/etc/nginx/conf.d/default.conf
@ -95,11 +106,11 @@ services:
depends_on:
- content-app
volumes:
- ./docker-compose/nginx.conf:/etc/nginx/conf.d/default.conf
- ./docker/proxy/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- internal
ports:
- 4000:80
networks:
? internal
internal:

View File

@ -1,15 +0,0 @@
# ACA with ACS Community 6.0ea
To run ACA together with the latest ACS community (6.0) use the following command:
```sh
docker-compose up
```
The ACA is served on the port 3000.
If you want to teardown the environment, use the following command:
```sh
docker-compose down
```

View File

@ -1,94 +0,0 @@
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:master-latest
depends_on:
- alfresco
networks:
- internal
ports:
- 3001:80
# 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:
- 3000:80
networks:
internal:

View File

@ -1,45 +0,0 @@
server {
listen *:80;
set $allowOriginSite *;
proxy_pass_request_headers on;
proxy_pass_header Set-Cookie;
access_log off;
location / {
proxy_pass http://content-app;
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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -52,10 +52,6 @@ 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

31
docker/nginx.conf Normal file
View File

@ -0,0 +1,31 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 8080;
server_name localhost;
root /usr/share/nginx/html;
index index.html index.htm;
include /etc/nginx/mime.types;
gzip on;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
location / {
try_files $uri $uri/ /index.html;
}
location ~ \.html$ {
add_header Cache-Control "private, no-cache, no-store, must-revalidate";
add_header Expires "Sat, 01 Jan 2000 00:00:00 GMT";
add_header Pragma no-cache;
}
}
}

29
docker/proxy/nginx.conf Normal file
View File

@ -0,0 +1,29 @@
server {
listen *:80;
set $allowOriginSite *;
proxy_pass_request_headers on;
proxy_pass_header Set-Cookie;
access_log off;
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 / {
proxy_pass http://content-app:8080;
}
location /alfresco/ {
proxy_pass http://alfresco:8080;
}
location /share/ {
proxy_pass http://share:8080;
}
}

View File

@ -1,9 +1,14 @@
---
Title: Alfresco Content Application
Github only: true
---
# Alfresco Content Application
<!-- markdownlint-disable MD033 -->
The Alfresco Content Application a file management application built using
[Alfresco Application Development Framework (ADF)](https://github.com/Alfresco/alfresco-ng2-components) components and was generated with [Angular CLI](https://github.com/angular/angular-cli).
[Alfresco Application Development Framework (ADF)](https://www.alfresco.com/abn/adf/docs) components and was generated with [Angular CLI](https://github.com/angular/angular-cli).
## Documentation
@ -15,6 +20,19 @@ The documentation is divided into the following sections:
- [Tutorials](/tutorials/): Exploration of development techniques in depth.
- [Help](/help): Details of further help and support available.
## Compatibility
| ACA Version | Built with | Tested on |
| ----------- | ---------- | --------- |
| ACA 1.7 | ADF 3.0.0 | ACS 6.1 |
| ACA 1.6 | ADF 2.6.1 | ACS 6.1 |
| ACA 1.5 | ADF 2.6.0 | ACS 6.0 |
| ACA 1.4 | ADF 2.5.0 | ACS 6.0 |
| ACA 1.3 | ADF 2.4.0 | ACS 6.0 |
| ACA 1.2 | ADF 2.3.0 | ACS 5.2 |
| ACA 1.1 | ADF 2.2.0 | ACS 5.2 |
| ACA 1.0 | ADF 2.0.0 | ACS 5.2 |
## How to contribute
Want to file a bug, contribute some code, or improve documentation? Excellent!

44
docs/abn-tree.yml Normal file
View File

@ -0,0 +1,44 @@
- features:
title: App features
children:
- user-interface-layout.md: User interface layout
- header.md: Header
- side-navigation.md: Side navigation
- document-list-layout.md: Document List Layout
- file-viewer.md: File Viewer
- info-drawer.md: Info Drawer
- version-manager.md: Version Manager
- search-results.md: Search results
- getting-started:
title: Getting started
children:
- prerequisites.md: Prerequisites
- building-from-source.md: Building from source
- internationalization.md: Internationalization
- cors.md: CORS
- configuration.md: Configuration
- navigation.md: Navigation
- docker.md: Docker
- extending:
title: extending
children:
- extensibility-features.md: Extensibility features
- extension-format.md: Extension format
- routes.md: Routes
- components.md: Components
- actions.md: Actions
- application-actions.md: Application actions
- rules.md: Rules
- application-features.md: Application features
- icons.md: Custom icons
- registration.md: Registration
- creating-custom-evaluators.md: Creating custom evaluators
- tutorials.md: Tutorials
- redistributable-libraries.md: Redistributable libraries
- tutorials:
title: Tutorials
children:
- introduction-to-extending.md: Introduction to extending ACA
- custom-route-with-parameters.md: Custom route with parameters
- dialog-actions.md: Dialog actions
- help.md: 'Get help'

View File

@ -1,4 +1,6 @@
---
Title: Extending
Github only: true
---
# Extending

View File

@ -1,8 +1,11 @@
---
Title: Actions
---
# Actions
Below are the details of the JSON properties that are used to define actions.
| Name | Description |
| -- | -- |
| **id** | Unique identifier. |

View File

@ -1,10 +1,13 @@
---
Title: Application Actions
---
# Application Actions
Application is using NgRx (Reactive libraries for Angular, inspired by Redux).
To get more information on NxRx please refer to the following resources:
The app uses **NgRx** (Reactive libraries for Angular, inspired by Redux)
to implement application actions.
For more information on NgRx, please refer to the following resources:
- [Comprehensive Introduction to @ngrx/store](https://gist.github.com/btroncone/a6e4347326749f938510)
@ -40,10 +43,8 @@ export class MyService {
You can invoke every application action from the extensions, i.e. buttons, menus, etc.
<p class="tip">
Many of the actions take currently selected nodes if no payload provided.
**Tip:** Many of the actions take currently selected nodes if no payload provided.
That simplifies declaring and invoking actions from the extension files.
</p>
In the example below, we create a new entry to the "NEW" menu dropdown
and provide a new `Create Folder (plugin1)` command that invokes the `CREATE_FOLDER` application action.
@ -75,42 +76,48 @@ and perform document list reload if needed.
Below is the list of public actions types you can use in the plugin definitions as a reference to the action:
| Name | Payload | Description |
| -- | -- | -- |
| SET_CURRENT_FOLDER | Node | Notify components about currently opened folder. |
| SET_CURRENT_URL | string | Notify components about current browser URL. |
| SET_USER_PROFILE | Person | Assign current user profile. |
| TOGGLE_INFO_DRAWER | n/a | Toggle info drawer for the selected node. |
| ADD_FAVORITE | MinimalNodeEntity[] | Add nodes (or selection) to favorites. |
| REMOVE_FAVORITE | MinimalNodeEntity[] | Removes nodes (or selection) from favorites. |
| DELETE_LIBRARY | string | Delete a Library by id. Takes selected node if payload not provided. |
| CREATE_LIBRARY | n/a | Invoke a "Create Library" dialog. |
| SET_SELECTED_NODES | MinimalNodeEntity[] | Notify components about selected nodes. |
| DELETE_NODES | MinimalNodeEntity[] | Delete the nodes (or selection). Supports undo actions. |
| UNDO_DELETE_NODES | any[] | Reverts deletion of nodes (or selection). |
| RESTORE_DELETED_NODES | MinimalNodeEntity[] | Restores deleted nodes (or selection). Typically used with Trashcan. |
| PURGE_DELETED_NODES | MinimalNodeEntity[] | Permanently delete nodes (or selection). Typically used with Trashcan. |
| DOWNLOAD_NODES | MinimalNodeEntity[] | Download nodes (or selections). Creates a ZIP archive for folders or multiple items. |
| CREATE_FOLDER | string | Invoke a "Create Folder" dialog for the opened folder (or the parent folder id in the payload). |
| EDIT_FOLDER | MinimalNodeEntity | Invoke an "Edit Folder" dialog for the node (or selection). |
| SHARE_NODE | MinimalNodeEntity | Invoke a "Share" dialog for the node (or selection). |
| UNSHARE_NODES | MinimalNodeEntity[] | Remove nodes (or selection) from the shared nodes (does not remove content). |
| COPY_NODES | MinimalNodeEntity[] | Invoke a "Copy" dialog for the nodes (or selection). Supports undo actions. |
| MOVE_NODES | MinimalNodeEntity[] | Invoke a "Move" dialog for the nodes (or selection). Supports undo actions. |
| MANAGE_PERMISSIONS | MinimalNodeEntity | Invoke a "Manage Permissions" dialog for the node (or selection). |
| MANAGE_VERSIONS | MinimalNodeEntity | Invoke a "Manage Versions" dialog for the node (or selection). |
| NAVIGATE_URL | string | Navigate to a given route URL within the application. |
| NAVIGATE_ROUTE | any[] | Navigate to a particular Route (supports parameters). |
| NAVIGATE_FOLDER | MinimalNodeEntity | Navigate to a folder based on the Node properties. |
| NAVIGATE_PARENT_FOLDER | MinimalNodeEntity | Navigate to a containing folder based on the Node properties. |
| NAVIGATE_LIBRARY | string | Navigate to library. |
| SEARCH_BY_TERM | string | Perform a simple search by the term and navigate to Search results. |
| SNACKBAR_INFO | string | Show information snackbar with the message provided. |
| SNACKBAR_WARNING | string | Show warning snackbar with the message provided. |
| SNACKBAR_ERROR | string | Show error snackbar with the message provided. |
| UPLOAD_FILES | n/a | Invoke "Upload Files" dialog and upload files to the currently opened folder. |
| UPLOAD_FOLDER | n/a | Invoke "Upload Folder" dialog and upload selected folder to the currently opened one. |
| VIEW_FILE | MinimalNodeEntity | Preview the file (or selection) in the Viewer. |
| PRINT_FILE | MinimalNodeEntity | Print the file opened in the Viewer (or selected). |
| FULLSCREEN_VIEWER | n/a | Enters fullscreen mode to view the file opened in the Viewer. |
| LOGOUT | n/a | Log out and redirect to Login screen. |
| Name | Payload | Description |
| ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------- |
| SET_CURRENT_FOLDER | Node | Notify components about currently opened folder. |
| SET_CURRENT_URL | string | Notify components about current browser URL. |
| SET_USER_PROFILE | Person | Assign current user profile. |
| TOGGLE_INFO_DRAWER | n/a | Toggle info drawer for the selected node. |
| ADD_FAVORITE | MinimalNodeEntity[] | Add nodes (or selection) to favorites. |
| REMOVE_FAVORITE | MinimalNodeEntity[] | Removes nodes (or selection) from favorites. |
| DELETE_LIBRARY | string | Delete a Library by id. Takes selected node if payload not provided. |
| CREATE_LIBRARY | n/a | Invoke a "Create Library" dialog. |
| SET_SELECTED_NODES | MinimalNodeEntity[] | Notify components about selected nodes. |
| DELETE_NODES | MinimalNodeEntity[] | Delete the nodes (or selection). Supports undo actions. |
| UNDO_DELETE_NODES | any[] | Reverts deletion of nodes (or selection). |
| RESTORE_DELETED_NODES | MinimalNodeEntity[] | Restores deleted nodes (or selection). Typically used with Trashcan. |
| PURGE_DELETED_NODES | MinimalNodeEntity[] | Permanently delete nodes (or selection). Typically used with Trashcan. |
| DOWNLOAD_NODES | MinimalNodeEntity[] | Download nodes (or selections). Creates a ZIP archive for folders or multiple items. |
| CREATE_FOLDER | string | Invoke a "Create Folder" dialog for the opened folder (or the parent folder id in the payload). |
| EDIT_FOLDER | MinimalNodeEntity | Invoke an "Edit Folder" dialog for the node (or selection). |
| SHARE_NODE | MinimalNodeEntity | Invoke a "Share" dialog for the node (or selection). |
| UNSHARE_NODES | MinimalNodeEntity[] | Remove nodes (or selection) from the shared nodes (does not remove content). |
| COPY_NODES | MinimalNodeEntity[] | Invoke a "Copy" dialog for the nodes (or selection). Supports undo actions. |
| MOVE_NODES | MinimalNodeEntity[] | Invoke a "Move" dialog for the nodes (or selection). Supports undo actions. |
| MANAGE_PERMISSIONS | MinimalNodeEntity | Invoke a "Manage Permissions" dialog for the node (or selection). |
| MANAGE_VERSIONS | MinimalNodeEntity | Invoke a "Manage Versions" dialog for the node (or selection). |
| NAVIGATE_URL | string | Navigate to a given route URL within the application. |
| NAVIGATE_ROUTE | any[] | Navigate to a particular Route (supports parameters). |
| NAVIGATE_FOLDER | MinimalNodeEntity | Navigate to a folder based on the Node properties. |
| NAVIGATE_PARENT_FOLDER | MinimalNodeEntity | Navigate to a containing folder based on the Node properties. |
| NAVIGATE_LIBRARY | string | Navigate to library. |
| SEARCH_BY_TERM | string | Perform a simple search by the term and navigate to Search results. |
| SNACKBAR_INFO | string | Show information snackbar with the message provided. |
| SNACKBAR_WARNING | string | Show warning snackbar with the message provided. |
| SNACKBAR_ERROR | string | Show error snackbar with the message provided. |
| UPLOAD_FILES | n/a | Invoke "Upload Files" dialog and upload files to the currently opened folder. |
| UPLOAD_FOLDER | n/a | Invoke "Upload Folder" dialog and upload selected folder to the currently opened one. |
| UPLOAD_FILE_VERSION | n/a | Invoke "New File Version" dialog. |
| VIEW_FILE | MinimalNodeEntity | Preview the file (or selection) in the Viewer. |
| UNLOCK_WRITE | NodeEntry | Unlock file from read only mode |
| PRINT_FILE | MinimalNodeEntity | Print the file opened in the Viewer (or selected). |
| FULLSCREEN_VIEWER | n/a | Enters fullscreen mode to view the file opened in the Viewer. |
| LOGOUT | n/a | Log out and redirect to Login screen. |
| RELOAD_DOCUMENT_LIST | n/a | Reload active document list |
| TOGGLE_SEARCH_FILTER | n/a | Toggle Filter component visibility in Search Results. |
| SHOW_SEARCH_FILTER | n/a | Show Filter component in Search Results. |
| HIDE_SEARCH_FILTER | n/a | Hide Filter component in Search Results |

View File

@ -1,4 +1,5 @@
---
Title: Application Features
---
# Application Features
@ -30,7 +31,6 @@ All the customizations are stored in the `features` section of the configuration
"contextMenu": [],
"viewer": {
"toolbarActions:": [],
"toolbarMoreMenu:": [],
"openWith": [],
"content": []
},
@ -117,9 +117,7 @@ You can populate the menu with an extra entries like in the example below:
Please refer to the [Content Actions](/extending/application-features#content-actions) section for more details on supported properties.
<p class="tip">
It is also possible to update or disable existing entries from within the external extension files. You will need to know the `id` of the target element to customize.
</p>
**Tip:** It is also possible to update or disable existing entries from within the external extension files. You will need to know the `id` of the target element to customize.
## Navigation Bar
@ -235,21 +233,19 @@ The example above renders two tabs:
All corresponding components must be registered for runtime use.
<p class="tip">
See the [Registration](/extending/registration) section for more details
**Tip:** See the [Registration](/extending/registration) section for more details
on how to register your own entries to be re-used at runtime.
</p>
### Tab properties
| Name | Description |
| ------------- | ----------------------------------------------------------- |
| **id** | Unique identifier. |
| **component** | The main [component](/extending/components) to use for the route. |
| **title** | Tab title or resource key. |
| icon | Tab icon |
| disabled | Toggles disabled state. Can be assigned from other plugins. |
| order | The order of the element. |
| Name | Description |
| ------------- | ----------------------------------------------------------------- |
| **id** | Unique identifier. |
| **component** | The main [component](/extending/components) to use for the route. |
| **title** | Tab title or resource key. |
| icon | Tab icon |
| disabled | Toggles disabled state. Can be assigned from other plugins. |
| order | The order of the element. |
### Tab components
@ -378,7 +374,6 @@ Viewer component in ACA supports the following extension points:
"viewer": {
"content": [],
"toolbarActions:": [],
"toolbarMoreMenu:": [],
"openWith": []
}
}
@ -425,6 +420,22 @@ Every custom component receives the following properties at runtime:
| url | string | File content URL. |
| extension | string | File name extension. |
#### Rules
You can also provide a rule for the `disabled` state.
That allows to provide conditional availability for Viewer extensions based on external factors.
```json
{
"id": "app.viewer.pdf",
"fileExtension": "png",
"component": "app.components.tabs.metadata",
"rules": {
"disabled": "isViewerDisabled"
}
}
```
### Toolbar actions
The default toolbar actions from the ACA viewer can be customized through extensions to be replaced, modified or disabled.
@ -451,15 +462,13 @@ New viewer toolbar actions can also be added from the extensions config:
"visible": "app.toolbar.versions"
}
}
],
"toolbarMoreMenu": [...]
]
}
}
}
```
The ADF Viewer component allows you to provide custom entries for the `More` menu button on the toolbar.
The ACA provides an extension point for this menu that you can utilize to populate custom menu items:
You can also provide sub-menus:
```json
{
@ -469,19 +478,27 @@ The ACA provides an extension point for this menu that you can utilize to popula
"features": {
"viewer": {
"toolbarActions": [...],
"toolbarMoreMenu": [
"toolbarActions": [
{
"id": "app.viewer.share",
"order": 300,
"title": "Share",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
"id": "app.toolbar.more",
"type": "menu",
"order": 10000,
"icon": "more_vert",
"title": "APP.ACTIONS.MORE",
"children": [
{
"id": "app.viewer.share",
"order": 300,
"title": "Share",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
}
]
}
]
}
@ -532,69 +549,72 @@ As with other content actions, custom plugins can disable, update or extend `Ope
## Content metadata presets
The content metadata presets are needed by the [Content Metadata Component](https://alfresco.github.io/adf-component-catalog/components/ContentMetadataComponent.html#readme) to render the properties of metadata aspects for a given node.
The content metadata presets are needed by the [Content Metadata Component](https://www.alfresco.com/abn/adf/docs/content-services/content-metadata-card.component/) to render the properties of metadata aspects for a given node.
The different aspects and their properties are configured in the `app.config.json` file, but they can also be set on runtime through extension files.
Configuring these presets from `app.extensions.json` will overwrite the default application setting.
Configuring these presets from `app.extensions.json` will overwrite the default application setting.
Settings them from custom plugins allows user to disable, update or extend these presets.
Check out more info about merging extensions [here](/extending/extension-format#merging-properties).
The `content-metadata-presets` elements can be switched off by setting the `disabled` property.
This can be applied also for nested items, allowing disabling down to aspect level.
This can be applied also for nested items, allowing disabling down to aspect level.
<p class="tip">
In order to modify or disable existing entries, you need to know the id of the target element, along with its parents ids.
</p>
**Tip:** In order to modify or disable existing entries, you need to know the id of the target element, along with its parents ids.
Your extensions can perform the following actions at runtime:
* Add new presets items.
* Add new items to existing presets at any level.
* Disable specific items down to the aspect level.
* Modify any existing item based on id.
- Add new presets items.
- Add new items to existing presets at any level.
- Disable specific items down to the aspect level.
- Modify any existing item based on id.
Regarding properties, you can either:
* Add new properties to existing aspect, or
* Redefine the properties of an aspect.
Review this code snippet to see how you can overwrite the properties for `exif:exif` aspect from an external plugin:
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"content-metadata-presets": [
{
"id": "app.content.metadata.custom",
"custom": [
{
"id": "app.content.metadata.customGroup",
"items": [
{
"id": "app.content.metadata.exifAspect",
"disabled": true
},
{
"id": "app.content.metadata.exifAspect2",
"aspect": "exif:exif",
"properties": [
"exif:orientation",
"exif:manufacturer",
"exif:model",
"exif:software"
]
}
]
}
]
}
]
}
}
```
This external plugin disables the initial `exif:exif` aspect already defined in the `app.extensions.json` and defines other properties for the `exif:exif` aspect.
- Add new properties to existing aspect, or
- Redefine the properties of an aspect.
Review this code snippet to see how you can overwrite the properties for `exif:exif` aspect from an external plugin:
```json
{
"$schema": "../../../extension.schema.json",
"$version": "1.0.0",
"$name": "plugin1",
"features": {
"content-metadata-presets": [
{
"id": "app.content.metadata.custom",
"custom": [
{
"id": "app.content.metadata.customGroup",
"items": [
{
"id": "app.content.metadata.exifAspect",
"disabled": true
},
{
"id": "app.content.metadata.exifAspect2",
"aspect": "exif:exif",
"properties": [
"exif:orientation",
"exif:manufacturer",
"exif:model",
"exif:software"
]
}
]
}
]
}
]
}
}
```
This external plugin disables the initial `exif:exif` aspect already defined in the `app.extensions.json` and defines other properties for the `exif:exif` aspect.
Here is the initial setting from `app.extension.json`:
```json
...
"content-metadata-presets": [
@ -630,8 +650,7 @@ Here is the initial setting from `app.extension.json`:
]
...
```
<p class="tip">
In order to allow the content-metadata presets to be extended, the settings from `app.config.json` must be copied to the `app.extensions.json` file and its ids must be added to all the items.
```
**Tip:** In order to allow the content-metadata presets to be extended, the settings from `app.config.json` must be copied to the `app.extensions.json` file and its ids must be added to all the items.
Having ids allows external plugins to extend the current setting.
</p>

View File

@ -1,4 +1,5 @@
---
Title: Components
---
# Components

View File

@ -1,11 +1,14 @@
---
Title: Creating custom evaluators
---
# Creating custom evaluators
Rule evaluators are plain JavaScript (or TypeScript) functions that take `RuleContext` references and an optional list of `RuleParameter` instances.
Application provides a special [RuleEvaluator](https://github.com/Alfresco/alfresco-content-app/blob/master/src/app/extensions/rule.extensions.ts#L30) type alias for evaluator functions:
Application provides a special
[RuleEvaluator](https://github.com/Alfresco/alfresco-ng2-components/blob/development/lib/extensions/src/lib/config/rule.extensions.ts)
type alias for evaluator functions:
```ts
export type RuleEvaluator = (context: RuleContext, ...args: any[]) => boolean;
@ -22,7 +25,7 @@ export function hasSelection(
}
```
The `context` is a reference to a special instance of the [RuleContext](https://github.com/Alfresco/alfresco-content-app/blob/master/src/app/extensions/rule.extensions.ts#L32) type,
The `context` is a reference to a special instance of the [RuleContext](https://github.com/Alfresco/alfresco-ng2-components/blob/development/lib/extensions/src/lib/config/rule.extensions.ts) type,
that provides each evaluator access to runtime entities.
```ts
@ -62,7 +65,5 @@ extensions.setEvaluators({
Now, the `plugin1.rules.hasSelection` evaluator can be used as an inline rule reference,
or part of the composite rule like `core.every`.
<p class="tip">
See the [Registration](/extending/registration) section for more details
**Tip:** See the [Registration](/extending/registration) section for more details
on how to register your own entries to be re-used at runtime.
</p>

View File

@ -1,4 +1,5 @@
---
Title: Extensibility features
---
# Extensibility features

View File

@ -1,4 +1,5 @@
---
Title: Extension format
---
# Extension format
@ -24,11 +25,9 @@ The format is represented by a JSON file with the structure similar to the follo
## Schema
You can find the JSON schema at the project root folder: [extension.schema.json](https://github.com/Alfresco/alfresco-content-app/blob/master/extension.schema.json).
You can find the JSON schema at the project root folder: [extension.schema.json](../../extension.schema.json).
<p class="tip">
The Schema allows you to validate extension files, provides code completion and documentation hints.
</p>
**Tip:** The Schema allows you to validate extension files, provides code completion and documentation hints.
```json
{
@ -53,10 +52,8 @@ The order of declaration defines the order of loading.
}
```
<p class="warning">
All extension files are merged together at runtime.
**Note:** All extension files are merged together at runtime.
This allows plugins to overwrite the code from the main application or to alter other plugins.
</p>
## Startup behavior
@ -68,10 +65,8 @@ For the sake of speed the files are loaded in parallel, however once everything
After all the external files are fetched, the `Loader` sorts them, removes the metadata properties and stacks the resulting JSON objects on top of each other.
<p class="tip">
Any top-level property name that starts with the `$` symbol is considered metadata and does not participate in the merge process.
**Tip:** Any top-level property name that starts with the `$` symbol is considered metadata and does not participate in the merge process.
That allows a plugin to carry extra information for maintenance and visualisation purposes, for example: `$name`, `$version`, `$description`, `$license`, etc.
</p>
### Merging properties
@ -111,10 +106,8 @@ Final result:
Note that as a result we have two unique properties `plugin1.key` and `plugin2.key`,
and also a `plugin1.text` that was first defined in the `Plugin 1`, but then overwritten by the `Plugin 2`.
<p class="tip">
JSON merging is a very powerful concept as it gives you the ability to alter any base application settings,
**Tip:** JSON merging is a very powerful concept as it gives you the ability to alter any base application settings,
or toggle features in other plugins without rebuilding the application or corresponding plugin libraries.
</p>
### Merging objects
@ -215,9 +208,7 @@ You can find more details in the [Disabling Content](/extending/extension-format
The extension `Loader` provides a special support for merging Arrays.
By default, two collections will be merged into a single array unless objects have `id` properties.
<p class="tip">
If array contains two objects with the same `id` property, the objects will be merged rather than appended.
</p>
**Tip:** If the array contains two objects with the same `id` property, the objects will be merged rather than appended.
Before: Plugin 1

View File

@ -1,3 +1,7 @@
---
Title: Custom Icons
---
# Custom Icons
You can register and use custom `.svg` icons with toolbars, context menus, etc.

View File

@ -1,4 +1,5 @@
---
Title: Redistributable libraries
---
# Redistributable libraries
@ -121,10 +122,8 @@ Update the root `package.json` file and append the following entry to the `scrip
You can now use that script to build the library and copy assets to the output folder.
<p class="tip">
It is good practice to provide installation instructions for your library in the `README.md` file.
**Tip:** It is good practice to provide installation instructions for your library in the `README.md` file.
Be sure to mention that developers should have a build rule to copy your plugin definition file to the `assets/plugins` folder of the main application.
</p>
## Publishing library to NPM
@ -155,9 +154,7 @@ npm install my-extension
This installs the library and all its dependencies.
<p class="warning">
You do not need to install the library in the original workspace as the application is already configured to use the local version from the `dist` folder.
</p>
**Note:** You do not need to install the library in the original workspace as the application is already configured to use the local version from the `dist` folder.
### Copy assets
@ -222,6 +219,4 @@ npm start
Click the `My Extension` link and in the main content area you will see the extension component coming from your library.
<p class="warning">
Depending on the application setup, you may need enabling external plugins via the `Settings` dialog available for `admin` users (clicking the application profile button).
</p>
**Note:** Depending on the application setup, you may need enabling external plugins via the `Settings` dialog available for `admin` users (clicking the application profile button).

View File

@ -1,4 +1,5 @@
---
Title: Registration
---
# Registration
@ -16,7 +17,7 @@ and use the following snippet to register custom content:
import { ExtensionsModule, ExtensionService } from '@alfresco/adf-extensions';
@NgModule({
imports: [ ExtensionsModule.forChild() ]
imports: [ ExtensionsModule ]
declarations: [ MyComponent1, MyLayout ],
entryComponents: [ MyComponent1, MyLayout ]
})
@ -41,13 +42,8 @@ export class MyExtensionModule {
}
```
Use `ExtensionsModule.forChild()` when importing into the child modules,
and `ExtensionsModule.forRoot()` for the main application module.
<p class="warning">
According to Angular rules, all components that are created dynamically at runtime
**Note:** According to Angular rules, all components that are created dynamically at runtime
need to be registered within the `entryComponents` section of the NgModule.
</p>
The Registration API is not limited to the custom content only.
You can replace any existing entries by replacing the values from your module.

View File

@ -1,4 +1,5 @@
---
Title: Routes
---
# Routes
@ -37,10 +38,8 @@ Use the `app.layout.main` value for the `layout` property to get the default app
with header, navigation sidebar and main content area.
You can register any component to back the `app.layout.main` value.
<p class="tip">
By default, the `app.layout.main` is used if you do not specify any custom values.
**Tip:** By default, the `app.layout.main` is used if you do not specify any custom values.
Use `blank` if you want your route component take the whole page.
</p>
You can define the full route schema like in the next example:

View File

@ -1,10 +1,10 @@
---
Title: Rules
---
# Rules
Rules allow evaluating conditions for extension components.
For example, you can disable or hide elements based on certain rules.
Rules allow you to evaluate conditions for extension components, so you can disable or hide elements based on certain rules, for example.
Every rule is backed by a condition evaluator.
@ -46,10 +46,8 @@ Rules can accept other rules as parameters:
}
```
<p class="tip">
You can also negate any rule by utilizing a `!` prefix:
**Tip:** You can also negate any rule by utilizing a `!` prefix:
`!app.navigation.isTrashcan` is the opposite of the `app.navigation.isTrashcan`.
</p>
It is also possible to use inline references to registered evaluators without declaring rules,
in case you do not need providing extra parameters, or chaining multiple rules together.
@ -131,26 +129,31 @@ The button will be visible only when the linked rule evaluates to `true`.
## Application Evaluators
| Key | Description |
| ------------------------------- | ------------------------------------------------------------ |
| app.selection.canDelete | User has permission to delete selected node(s). |
| app.selection.canDownload | User can download selected node(s). |
| app.selection.notEmpty | At least one node is selected. |
| app.selection.canUnshare | User is able to remove selected node(s) from public sharing. |
| app.selection.canAddFavorite | User can add selected node(s) to favorites. |
| app.selection.canRemoveFavorite | User can remove selected node(s) from favorites. |
| app.selection.first.canUpdate | User has permission to update selected node(s). |
| app.selection.file | A single File node is selected. |
| app.selection.file.canShare | User is able to share the selected file. |
| app.selection.file.isShared | A shared node is selected |
| app.selection.file.isLocked | File is locked for editing |
| app.selection.library | A single Library node is selected. |
| app.selection.isPrivateLibrary | A private Library node is selected. |
| app.selection.hasLibraryRole | The selected Library node has a role property. |
| app.selection.hasNoLibraryRole | The selected Library node has no role property. |
| app.selection.folder | A single Folder node is selected. |
| app.selection.folder.canUpdate | User has permissions to update the selected folder. |
| repository.isQuickShareEnabled | Whether the quick share repository option is enabled or not. |
| Key | Description |
| ----------------------------------- | ------------------------------------------------------------ |
| app.selection.canDelete | User has permission to delete selected node(s). |
| app.selection.canDownload | User can download selected node(s). |
| app.selection.notEmpty | At least one node is selected. |
| app.selection.canUnshare | User is able to remove selected node(s) from public sharing. |
| app.selection.canAddFavorite | User can add selected node(s) to favorites. |
| app.selection.canRemoveFavorite | User can remove selected node(s) from favorites. |
| app.selection.first.canUpdate | User has permission to update selected node(s). |
| app.selection.file | A single File node is selected. |
| app.selection.file.canShare | User is able to share the selected file. |
| app.selection.file.isShared | A shared node is selected. |
| app.selection.file.isLocked | File is locked for editing. |
| app.selection.file.isLockOwner | File is locked and current user is the lock owner. |
| app.selection.file.canUploadVersion | User can update file version. |
| app.selection.library | A single Library node is selected. |
| app.selection.isPrivateLibrary | A private Library node is selected. |
| app.selection.hasLibraryRole | The selected Library node has a role property. |
| app.selection.hasNoLibraryRole | The selected Library node has no role property. |
| app.selection.folder | A single Folder node is selected. |
| app.selection.folder.canUpdate | User has permissions to update the selected folder. |
| app.selection.folder.canUpdate | User has permissions to update the selected folder. |
| app.selection.file.canLock | User has permissions to lock file. |
| app.selection.file.canUnlock | User has permissions to unlock file. |
| repository.isQuickShareEnabled | Whether the quick share repository option is enabled or not. |
## Navigation Evaluators
@ -159,32 +162,34 @@ The application exposes a set of navigation-related evaluators to help developer
The negated evaluators are provided just to simplify development, and to avoid having complex rule trees just to negate the rules,
for example mixing `core.every` and `core.not`.
<p class="tip">
You can also negate any rule by utilizing a `!` prefix:
**Tip:** You can also negate any rule by utilizing a `!` prefix:
`!app.navigation.isTrashcan` is the opposite of the `app.navigation.isTrashcan`.
</p>
| Key | Description |
| --------------------------------- | ------------------------------------------------------- |
| app.navigation.folder.canCreate | User can create content in the currently opened folder. |
| app.navigation.folder.canUpload | User can upload content to the currently opened folder. |
| app.navigation.isTrashcan | User is using the **Trashcan** page. |
| app.navigation.isNotTrashcan | Current page is not a **Trashcan**. |
| app.navigation.isLibraries | User is using a **Libraries** page. |
| app.navigation.isNotLibraries | Current page is not a **Libraries** page. |
| app.navigation.isSharedFiles | User is using the **Shared Files** page. |
| app.navigation.isNotSharedFiles | Current page is not **Shared Files**. |
| app.navigation.isFavorites | User is using the **Favorites** page. |
| app.navigation.isNotFavorites | Current page is not **Favorites** |
| app.navigation.isRecentFiles | User is using the **Recent Files** page. |
| app.navigation.isNotRecentFiles | Current page is not **Recent Files**. |
| app.navigation.isSearchResults | User is using the **Search Results** page. |
| app.navigation.isNotSearchResults | Current page is not the **Search Results**. |
| Key | Description |
| --------------------------------- | ---------------------------------------------------------------- |
| app.navigation.folder.canCreate | User can create content in the currently opened folder. |
| app.navigation.folder.canUpload | User can upload content to the currently opened folder. |
| app.navigation.isTrashcan | User is using the **Trashcan** page. |
| app.navigation.isNotTrashcan | Current page is not a **Trashcan**. |
| app.navigation.isLibraries | User is using a **Libraries** or **Library Search Result** page. |
| app.navigation.isNotLibraries | Current page is not a **Libraries** page. |
| app.navigation.isSharedFiles | User is using the **Shared Files** page. |
| app.navigation.isNotSharedFiles | Current page is not **Shared Files**. |
| app.navigation.isFavorites | User is using the **Favorites** page. |
| app.navigation.isNotFavorites | Current page is not **Favorites**. |
| app.navigation.isRecentFiles | User is using the **Recent Files** page. |
| app.navigation.isNotRecentFiles | Current page is not **Recent Files**. |
| app.navigation.isSearchResults | User is using the **Search Results** page. |
| app.navigation.isNotSearchResults | Current page is not the **Search Results**. |
| app.navigation.isSharedPreview | Current page is preview **Shared Files**. |
| app.navigation.isFavoritesPreview | Current page is preview **Favorites**. |
| app.navigation.isSharedFileViewer | Current page is shared file preview page. |
| app.navigation.isPreview | Current page is **Preview**. |
| app.navigation.isPersonalFiles | Current page is **Personal Files**. |
| app.navigation.isLibraryFiles | Current page is **Library Files**. |
<p class="tip">
See [Registration](/extending/registration) section for more details
**Tip:** See the [Registration](/extending/registration) section for more details
on how to register your own entries to be re-used at runtime.
</p>
### Example

View File

@ -1,8 +1,11 @@
---
Title: Tutorials
---
# Tutorials
Below are some short tutorials that cover common tasks.
## Custom route with parameters
In this tutorial, we are going to implement the following features:

View File

@ -1,4 +1,6 @@
---
Title: Application features
Github only: true
---
# Application features

View File

@ -1,14 +1,15 @@
---
Title: Document List Layout
---
# Document List Layout
The main area of the application is composed of several individual ADF components:
1. [Breadcrumb](https://alfresco.github.io/adf-component-catalog/components/BreadcrumbComponent.html)
2. [Toolbar](https://alfresco.github.io/adf-component-catalog/components/ToolbarComponent.html)
3. [Document List](https://alfresco.github.io/adf-component-catalog/components/DocumentListComponent.html)
4. [Pagination](https://alfresco.github.io/adf-component-catalog/components/PaginationComponent.html)
1. [Breadcrumb](https://www.alfresco.com/abn/adf/docs/content-services/breadcrumb.component/)
2. [Toolbar](https://www.alfresco.com/abn/adf/docs/core/toolbar.component/)
3. [Document List](https://www.alfresco.com/abn/adf/docs/content-services/document-list.component/)
4. [Pagination](https://www.alfresco.com/abn/adf/docs/core/pagination.component/)
![](../images/doclist.png)
@ -19,150 +20,80 @@ The application has seven different Document List views which share commonalitie
Personal Files retrieves all content from the logged in user's home area (`/User Homes/<username>/`) in the repository;
if the user is admin who does not have a home folder then the repository root folder is shown.
Personal Files is the [Files](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/files) component,
Personal Files is the [Files](../../src/app/components/files) component,
using the [Nodes API](https://api-explorer.alfresco.com/api-explorer/#/nodes).
## File Libraries
File Libraries retrieves all the sites that the user is a member of including what type of site it is: public, moderated or private.
File Libraries is the [Libraries](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/libraries) component,
File Libraries is the [Libraries](../../src/app/components/libraries) component,
using the [Sites API](https://api-explorer.alfresco.com/api-explorer/#/sites).
When a user opens one of their sites then the content for the site's document library is shown.
To display the files and folders from a site (`/Sites/<siteid>/Document Library/`) the [Files](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/files) component,
To display the files and folders from a site (`/Sites/<siteid>/Document Library/`) the [Files](../../src/app/components/files) component,
using the [Nodes API](https://api-explorer.alfresco.com/api-explorer/#/nodes) is used.
## Shared Files
The Shared Files view aggregates all files that have been shared using the QuickShare feature in the content repository.
The [Shared Files](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/shared-files) component uses the [shared-links API](https://api-explorer.alfresco.com/api-explorer/#/shared-links)
and includes extra columns to display where the file is
[located](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/location-link)
The [Shared Files](../../src/app/components/shared-files) component uses the [shared-links API](https://api-explorer.alfresco.com/api-explorer/#/shared-links)
and includes extra columns to display where the file is located
in the content repository and who created the shared link.
## Recent Files
The Recent Files view shows all the files that have been created or modified within the last 30 days by the current user.
The [Recent Files](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/recent-files)
component uses the Search API to query SOLR for changes made by the user and includes an extra column to display where the file is
[located](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/location-link)
The [Recent Files](../../src/app/components/recent-files)
component uses the Search API to query SOLR for changes made by the user and includes an extra column to display where the file is located
in the content repository.
## Favorites
The Favorites view shows all files and folders from the content repository that have been marked as a favorite by the current user.
The [Favorites](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/favorites) component uses the
The [Favorites](../../src/app/components/favorites) component uses the
[favorites](https://api-explorer.alfresco.com/api-explorer/#/favorites) API to retrieve all the favorite nodes for the user
and includes an extra column to display where the file is
[located](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/location-link)
and includes an extra column to display where the file is located
in the content repository.
## Trash
The Trash view shows all the items that a user has deleted, admin will see items deleted by all users.
The actions available in this view are Restore and Permanently Delete.
The [Trashcan](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/trashcan) component uses the
The [Trashcan](../../src/app/components/trashcan) component uses the
[trashcan](https://api-explorer.alfresco.com/api-explorer/#/trashcan) API to retrieve the deleted items
and perform the actions requested by the user and includes an extra column to display where the item was
[located](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/location-link)
and perform the actions requested by the user and includes an extra column to display where the item was located
in the content repository before it was deleted.
## Search Results
The Search Results view shows the found items for a search query. It has a custom layout template and users can easily browse the results and perform actions on items.
For more information on the [SearchComponent](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/search), please also check this [Search Results](/features/search-results) section.
For more information on the [Search Component](../../src/app/components/search), please also check this [Search Results](/features/search-results) section.
Another custom template layout shows the results when searching for libaries so that users can find, join and favorite libraries that they aren't already members of.
## Actions and the Actions Toolbar
All the views incorporate the [toolbar](https://alfresco.github.io/adf-component-catalog/components/ToolbarComponent.html)
All the views incorporate the [toolbar](https://www.alfresco.com/abn/adf/docs/core/toolbar.component/)
component from the Alfresco Application Development Framework.
Actions are displayed in the toolbar when item(s) are selected, or a right click is performed; apart from the Trash view they all display the following actions when the current user has the necessary permissions,
actions are automatically hidden when the user does not have permission.
<table>
<thead>
<th>Action</th>
<th>File</th>
<th>Folder</th>
</thead>
<tbody>
<tr>
<td>View</td>
<td>
Opens the selected file using the <a href="https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/preview" target="_blank">Preview</a> component,
where the file cannot be displayed natively in a browser a PDF rendition is obtained from the repository.
</td>
<td>Not applicable</td>
</tr>
<tr>
<td>Download</td>
<td>Downloads single files to the user's computer, when multiple files are selected they are compressed into a ZIP and then downloaded.</td>
<td>Folders are automatically compressed into a ZIP and then downloaded to the user's computer.</td>
</tr>
<tr>
<td>Edit</td>
<td>Not applicable</td>
<td>The folder name and description can be edited in a dialog.</td>
</tr>
<tr>
<td>Favorite</td>
<td colspan="2">
Toggle the favorite mark on or off for files and folders, when multiple items are selected
and one or more are not favorites then the mark will be toggled on.
</td>
</tr>
<tr>
<td>Copy</td>
<td colspan="2">
Files and folders can be copied to another location in the content repository using the
<a href="https://alfresco.github.io/adf-component-catalog/components/ContentNodeSelectorComponent.html" target="_blank">content-node-selector</a> component;
once the copy action has completed the user is notified and can undo the action (which permanently deletes the created copies).
</td>
</tr>
<tr>
<td>Move</td>
<td colspan="2">
Files and folders can be moved to another location in the content repository using the
<a href="https://alfresco.github.io/adf-component-catalog/components/ContentNodeSelectorComponent.html" target="_blank">content-node-selector</a> component;
once the move action has completed the user is notified and can undo the action (which moves the items back to the original location).
</td>
</tr>
<tr>
<td>Share</td>
<td>
Create and copy a link to a file that can be shared, the links are accessible without granting permissions to the file, and do not require users to login to the application. Share links can automatically expire based on a date, the minimum expiry date is controlled by the Content Services repository, which is 1 day from the date of creation.
</td>
<td>
Not applicable.
</td>
</tr>
<tr>
<td>Delete</td>
<td colspan="2">
Files and folders can be deleted from their location in the content repository;
once the delete action has completed the user is notified and can undo the action (which restores the items from the trash).
</td>
</tr>
<tr>
<td>Manage Versions</td>
<td>
Versions of files can be viewed, uploaded, restored, downloaded and deleted by using the version manager dialog;
once each action has completed the list of versions is updated according to the change.
</td>
<td>Not applicable</td>
</tr>
<tr>
<td>Permissions</td>
<td>
Permissions on a file can be adjusted as required in a number of ways; disable inheritance from the parent folder, change a user or groups role and grant users/groups access.
</td>
<td>Not available</td>
</tr>
</tbody>
</table>
| Action | File | Folder |
| -- | -- | -- |
| Edit in Microsoft Office | Opens Word, Powerpoint and Excel files directly in your Microsoft Office applications, requires Alfresco Office Services | Not applicable |
| Edit offline | Downloads the file and locks it in the repository for offline editing | Not applicable |
| Upload a new version | Upload a new version for the selected file | Not applicable |
| Share | Create and copy a link to a file that can be shared, the links are accessible without granting permissions to the file, and do not require users to login to the application. Share links can automatically expire based on a date, the minimum expiry date is controlled by the Content Services repository, which is 1 day from the date of creation. | Not applicable |
| Download | Downloads single files to the user's computer, when multiple files are selected they are compressed into a ZIP and then downloaded. | Folders are automatically compressed into a ZIP and then downloaded to the user's computer. |
| View | Opens the selected file using the [Preview component](../../src/app/components/preview). If the file cannot be displayed natively in a browser, a PDF rendition is obtained from the repository. | Not applicable |
| Edit | Not applicable | The folder name and description can be edited in a dialog. |
| Favorite | Toggle the favorite mark on or off for files and folders. If multiple items are selected and one or more are not favorites then the mark will be toggled on. |
| Copy | Files and folders can be copied to another location in the content repository using the [Content node selector component](https://www.alfresco.com/abn/adf/docs/content-services/content-node-selector.component/). When the copy action has completed the user is notified and can undo the action (which permanently deletes the created copies). |
| Move | Files and folders can be moved to another location in the content repository using the [Content node selector component](https://www.alfresco.com/abn/adf/docs/content-services/content-node-selector.component/). When the move action has completed the user is notified and can undo the action (which moves the items back to the original location). |
| Delete | Files and folders can be deleted from their location in the content repository. When the delete action has completed the user is notified and can undo the action (which restores the items from the trash). |
| Manage Versions | Versions of files can be viewed, uploaded, restored, downloaded and deleted by using the version manager dialog. When each action has completed the list of versions is updated according to the change. | Not applicable |
| Permissions | Permissions on a file can be adjusted as required in a number of ways; disable inheritance from the parent folder, change a user or groups role and grant users/groups access. | Not available |
Besides the actions available in the toolbar users can
* single click on a file to view it, and a folder to open it

View File

@ -1,9 +1,12 @@
---
Title: File Viewer
---
# File Viewer
The File Viewer has been created using the [ViewerComponent](https://alfresco.github.io/adf-component-catalog/components/ViewerComponent.html) from the ADF. The Viewer has four main areas:
The File Viewer has been created using the [ViewerComponent](https://www.alfresco.com/abn/adf/core/viewer.component/) from ADF.
The Viewer has four main areas:
![File Viewer](../images/File-Viewer.png)
@ -23,7 +26,7 @@ The Header & Toolbar section of the viewer contains a number of features that re
## Content
The File Viewer consists of four separate views that handle displaying the content based on four types of content, covering various [file/mime](https://alfresco.github.io/adf-component-catalog/components/ViewerComponent.html#supported-file-formats) types:
The File Viewer consists of four separate views that handle displaying the content based on four types of content, covering various [file/mime](https://www.alfresco.com/abn/adf/core/viewer.component/#supported-file-formats) types:
- Document View: PDF files are displayed in the application File Viewer, for other document types (DOCX etc) then a PDF rendition is automatically retrieved.
- Image View: JPEG, PNG, GIF, BMP and SVG images are natively displayed in the application File Viewer.

View File

@ -1,9 +1,10 @@
---
Title: Header
---
# Header
The application [header](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/header) has three main elements.
The application [header](../../src/app/components/header) has three main elements.
1. [Logo and Color](#logo-and-color)
2. [Search](#search)
@ -14,13 +15,13 @@ The application [header](https://github.com/Alfresco/alfresco-content-app/tree/m
## Logo and Color
Logo & app primary color - logo and color are configurable by updating the
[app.config.json](https://github.com/Alfresco/alfresco-content-app/blob/master/src/app.config.json) file in the root folder of the project.
[app.config.json](../../src/app.config.json) file in the root folder of the project.
Please refer to the [Application Configuration](/getting-started/configuration) documentation for more information on how to change the logo and color.
## Search
The application [Search](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/search) -
uses the [ADF Search Component](https://github.com/Alfresco/alfresco-ng2-components/tree/master/lib/content-services/search).
The application [Search](../../src/app/components/search) -
uses the [ADF Search Component](https://www.alfresco.com/abn/adf/docs/content-services/search.component/).
The app provides a 'live' search feature, where users can open files and folders directly from the Search API results.
![Search Input](../images/search.png)
@ -31,9 +32,9 @@ with advanced filtering and faceted search.
## Current User
[Current User](https://github.com/Alfresco/alfresco-content-app/tree/development/src/app/components/current-user) -
[Current User](../../src/app/components/current-user) -
displays the user's name, and a menu where users can logout.
Optionally through updating the [app.config.json](https://github.com/Alfresco/alfresco-content-app/blob/master/src/app.config.json)
Optionally through updating the [app.config.json](../../src/app.config.json)
a language switching menu can be displayed.
![Current User](../images/current-user.png)

View File

@ -1,20 +1,23 @@
---
Title: Info Drawer
---
# Info Drawer
The Info Drawer displays node information in the right sidebar panel. It is created by using the [InfoDrawerComponent](https://alfresco.github.io/adf-component-catalog/components/InfoDrawerComponent.html). This info is available for both folder and file nodes.
The Info Drawer displays node information in the right sidebar panel.
It is created by using the [Info Drawer Component](https://www.alfresco.com/abn/adf/core/info-drawer.component/). This info is available for both folder and file nodes.
Currently, there are 2 tabs available: Properties and Versions.
## Properties tab
The Properties tab displays the node's metadata info by using the [ContentMetadataCardComponent](https://alfresco.github.io/adf-component-catalog/components/ContentMetadataCardComponent.html).
The Properties tab displays the node's metadata info by using the [Content Metadata Card Component](https://www.alfresco.com/abn/adf/core/content-metadata-card.component/).
![](images/content-metadata.png)
![](../images/content-metadata.png)
For more information, please check also the [ContentMetadataComponent](https://alfresco.github.io/adf-component-catalog/components/ContentMetadataComponent.html).
For more information, please check also the [Content Metadata Component](https://www.alfresco.com/abn/adf/core/content-metadata.component/).
## Comments tab
The Comments tab displays all comments made on the selected node in the respoistory by using the [CommentsComponent](https://alfresco.github.io/adf-component-catalog/components/CommentsComponent.html). Users can post new comments that will be displayed immediately.
The Comments tab displays all comments made on the selected node in the respoistory by using the [Comments Component](https://www.alfresco.com/abn/adf/core/comments.component/). Users can post new comments that will be displayed immediately.

View File

@ -1,19 +1,54 @@
---
Title: Search Results
---
# Search Results
Once you type the text in the Search Input component you are going to see the Search Results page
When you type queries into the Search Input component, the application will return the Search Results in a page. From the search results page you can open files and perform various actions depending on the permissions available for the selected item.
![Search Results](../images/aca-search-results.png)
This page consists of the following ADF components:
- [Search Filter](https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/content-services/search-filter.component.md)
- [Search Chip List](https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/content-services/search-chip-list.component.md)
- [Search Sorting Picker](https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/content-services/search-sorting-picker.component.md)
- [Document List](https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/content-services/document-list.component.md) with custom layout template
- [Search Filter](https://www.alfresco.com/abn/adf/docs/content-services/search-filter.component/)
- [Search Chip List](https://www.alfresco.com/abn/adf/docs/content-services/search-chip-list.component/)
- [Search Sorting Picker](https://www.alfresco.com/abn/adf/docs/content-services/search-sorting-picker.component/)
- [Document List](https://www.alfresco.com/abn/adf/docs/content-services/document-list.component/) with custom layout template
- [Info Drawer](/features/info-drawer) with Metadata and [Version Management](#version-manager)
- [Toolbar with basic actions](/features/document-list-layout#actions-and-the-actions-toolbar) like `Preview`, `Download`, `Favorite`, `Copy`, etc.
And also the Info Drawer, Toolbar and Node Selector dialogs for copy and move operations.
## Alfresco Full Text Search
The following table describes current support of the
[Alfresco Full Text Search](http://docs.alfresco.com/6.1/concepts/rm-searchsyntax-intro.html) (FTS) syntax
in the Content Application when using **Search Input** component.
| Feature | Full | Partial | N/A | Details |
| ---------------------------------------------------------------- | ---- | ------- | --- | ---------------------------------------------------------------------------------- |
| Search for a single term | 1.6 | | | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-single.html) |
| Search for a phrase | | 1.7 | | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-phrase.html) |
| Search for an exact term | 1.7 | | | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-exact.html) |
| Search for term expansion | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-term.html) |
| Search for conjunctions | 1.7 | | | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-conjunct.html) |
| Search for disjunctions | 1.7 | | | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-disjunct.html) |
| Search for negation | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-negate.html) |
| Search for optional, mandatory, and excluded elements of a query | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-optional.html) |
| Search in fields | | 1.7 | | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-fields.html) |
| Search for wildcards | | 1.7 | | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-wildcards.html) |
| Search for ranges | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-ranges.html) |
| Search for fuzzy matching | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-fuzzy.html) |
| Search for proximity | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-proximity.html) |
| Search for boosts | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-boosts.html) |
| Search for grouping | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-grouping.html) |
| Search for spans and positions | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-spans.html) |
| Escaping characters | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-escaping.html) |
| Mixed FTS ID behavior | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-ftsid.html) |
| Search for operator precedence | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-precedence.html) |
| Search query templates | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-querytemplates.html) |
| Search query literals | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-literals.html) |
| Search using date math | | | X | [Docs](https://docs.alfresco.com/6.0/concepts/rm-searchsyntax-datemaths.html) |
> **Partial** support means the feature supports basic scenarios
> and there are edge cases that are not yet fully tested and might not work.

View File

@ -1,10 +1,10 @@
---
Title: Side Navigation
---
# Side Navigation
The application [side navigation](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/sidenav) has two features:
a button menu and navigation links.
The application [side navigation](../../src/app/components/sidenav) has two features: a button menu and navigation links.
![Side Navigation](../images/side-nav.png)
@ -16,7 +16,7 @@ The New button displays a menu which provides three actions:
- Upload a file - invokes the operating system file browser and allows a user to select file(s) to upload into their current location in the content repository.
- Upload a folder - invokes the operating system folder browser and allows a user to select a folder to upload to their current location in the content repository.
When an upload starts the [upload component](https://github.com/Alfresco/alfresco-ng2-components/tree/master/lib/content-services/upload)
When an upload starts the [upload component](https://www.alfresco.com/abn/adf/docs/content-services/upload.component/)
is displayed which shows the user the progress of the uploads they have started.
The upload dialog persists on the screen and can be minimized; users are able to continue using the application whilst uploads are in progress
and uploads can be canceled which will stop uploads in progress or permanently delete already completed uploads.
@ -25,6 +25,6 @@ and uploads can be canceled which will stop uploads in progress or permanently d
## Navigation
The navigation links are configurable via the [app.config.json](https://github.com/Alfresco/alfresco-content-app/blob/master/src/app.config.json).
The navigation links are configurable via the [app.config.json](../../src/app.config.json).
Default configuration creates two sections.
See [Navigation](/getting-started/navigation) for more information about configuring the side navigation.

View File

@ -1,9 +1,10 @@
---
Title: User Interface - layout
---
# User Interface - layout
There are three main areas of the application controlled by the [Layout component](https://github.com/Alfresco/alfresco-content-app/tree/master/src/app/components/layout):
There are three main areas of the application controlled by the [Layout component](../../src/app/components/layout):
1. [Application Header](/features/header)
2. [Side Navigation](/features/side-navigation)

View File

@ -1,9 +1,10 @@
---
Title: Version Manager
---
# Version Manager
The versions of a file can be viewed and managed by using the [VersionManagerComponent](https://alfresco.github.io/adf-component-catalog/components/VersionManagerComponent.html).
The versions of a file can be viewed and managed by using the [Version Manager Component](https://www.alfresco.com/abn/adf/content-services/version-manager.component/).
There are 2 ways users can access the Version Manager:
@ -20,7 +21,7 @@ There are 2 ways users can access the Version Manager:
A new version for the selected file can be added by using this button. Users can upload a new file version using a file that is does not have the same name, or mime type as the current version, whilst allowing the user to choose the type of version (minor or major) and inputting supporting comments.
Please also check the [UploadVersionButtonComponent](https://alfresco.github.io/adf-component-catalog/components/UploadVersionButtonComponent.html).
Please also check the [UploadVersionButtonComponent](https://www.alfresco.com/abn/adf/content-services/upload-version-button.component/).
## Actions Menu
@ -39,4 +40,4 @@ In the app.config.json file, these are the current settings for the ACA version
Set the allowComments to false if the version comments should not be displayed on the version list.
Clicking to delete a version of a file triggers a confirmation dialog. Please see the [ConfirmDialogComponent](https://alfresco.github.io/adf-component-catalog/components/ConfirmDialogComponent.html) for more info.
Clicking to delete a version of a file triggers a confirmation dialog. Please see the [Confirm Dialog Component](https://github.com/Alfresco/alfresco-ng2-components/blob/development/lib/content-services/dialogs/confirm.dialog.ts) for more info.

View File

@ -1,4 +1,6 @@
---
Title: Getting started
Github only: true
---
# Getting started
@ -11,6 +13,7 @@ Learn how to start developing with the Alfresco Content Application.
- [Building from source](/getting-started/building-from-source)
- [Internationalization (i18n)](/getting-started/internationalization)
- [CORS](/getting-started/cors)
- [Single Sign-On](/getting-started/sso)
- [Configuration](/getting-started/configuration)
- [Navigation](/getting-started/navigation)
- [Docker](/getting-started/docker)
- [Docker](/getting-started/docker)

View File

@ -1,4 +1,5 @@
---
Title: Building from source
---
# Building from source
@ -8,7 +9,10 @@ The Content App is based on [Angular CLI](https://cli.angular.io), and you can u
## Prerequisites for building
- [Node.js](https://nodejs.org/en/) LTS
- [Angular CLI](https://cli.angular.io/) 1.7.3
- (optional) [Angular CLI](https://cli.angular.io/) 7.3.4 or later
> The Angular CLI libraries are already part of the setup.
> You may want installing it as a global (recommended) tool only if you intend using CLI commands separately.
## Cloning and running
@ -27,13 +31,11 @@ The application runs at port `4200` by default, and should automatically open in
The Content App provides a proxy configuration for a local development server that allows you to address specific scenarios with CORS and a native authentication dialog.
You can find settings in the "proxy.conf.js" file in the project root directory.
You can find settings in the `proxy.conf.js` file in the project root directory.
<p class="warning">
The proxy settings get automatically applied every time you run the application with the "npm start" script.
**Note:** The proxy settings get automatically applied every time you run the application with the `npm start` script.
You must restart the application every time you change its settings.
</p>
## Running unit tests
Run `npm test` to execute the unit tests via [Karma](https://karma-runner.github.io).
Run `npm test` to execute the unit tests via [Karma](https://karma-runner.github.io).

View File

@ -1,4 +1,5 @@
---
Title: Configuration
---
# Configuration
@ -48,35 +49,12 @@ Alternatively, you can provide a static address for the ACS server if necessary:
The "baseShareUrl" property tells the application how to construct the address where users will access shared files.
#### Default
When the default value is set the application will construct the File Share URL from the "ecmHost" property:
```json
{
...
"baseShareUrl": null,
...
"baseShareUrl": "{protocol}//{hostname}{:port}/#/preview/s"
}
```
#### Configuration
If you run the application from a different server than the Content Services server the "baseShareUrl" property should must be configured correctly, for example:
```json
{
...
"baseShareUrl": "http://{serveraddress}{:port}",
...
}
```
<p class="warning">
If you run the application as part of Tomcat and not in the root (subfolder), then "baseShareUrl" value should contain full address to the app, for example: "baseShareUrl": "http://{serveraddress}{:port}/{folder}".
</p>
## Application settings
There are many settings you can change to alter the default behavior of the application.
@ -106,7 +84,6 @@ The default logo displayed in the top left corner of the Alfresco Content Applic
2. In the app.config.json file, set the value of the application.logo to contain the name of the custom logo image: "logo": "/assets/images/[image-name].[extension]"
```json
{
...,
@ -148,9 +125,7 @@ By default, the application ships with the following rules already predefined:
}
```
<p class="tip">
You can get more details on the supported rules in the following article: <a href="https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/core/upload.service.md" target="_blank">Upload Service</a>.
</p>
**Tip:** You can find more details on the supported rules in the ADF [Upload Service](https://www.alfresco.com/abn/adf/docs/core/upload.service/) docs.
### Pagination settings
@ -174,6 +149,5 @@ You can change the default settings of the pagination that gets applied to all t
You can store any information in the application configuration file, and access it at runtime by using the `AppConfigService` service provided by ADF.
<p class="tip">
Please refer to the <a href="https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/core/app-config.service.md" target="_blank">AppConfigService</a> documentation to get more details on Application Configuration features and API's available.
</p>
**Tip:** Please refer to the ADF
[App Config Service](https://www.alfresco.com/abn/adf/docs/core/app-config.service/) documentation to get more details on the Application Configuration features and APIs available.

View File

@ -1,9 +1,11 @@
---
Title: CORS
---
# CORS
The Alfresco Content Application comes with the proxy configuration for Angular CLI to address CORS-related issues for development.
Also, the docker images contain Nginx settings needed for CORS when developing and debugging an application locally.
## Chrome Workaround

View File

@ -1,9 +1,11 @@
---
Title: Docker
---
# Docker
The ACA comes with the ACS 6.0 Community Edition preconfigured.
ACA comes with the ACS 6.0 Community Edition preconfigured.
The application runs in two modes:
- Development (runs latest source code, requires building application)
@ -26,17 +28,5 @@ Use the following command to stop all the containers:
npm run stop:docker
```
## Preview Mode
<p class="tip">
With this mode, you do not need building application from source code or installing dependencies.
</p>
To run the latest published container go to the `docker-compose` folder and start docker compose from there:
```sh
cd docker-compose
docker-compose up
```
The application is available at the `http://localhost:3000` address.
You can also develop the application and run in default port (4200),
it is going to use the same docker containers automatically.

View File

@ -1,4 +1,5 @@
---
Title: Internationalization
---
# Internationalization (i18n)
@ -22,7 +23,7 @@ The default language is English, however the current browser language is taken a
## User-defined language
You can allow users to set custom languages that are saved to their preferences.
The main application menu already has the [ADF Language Menu](https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/core/language-menu.component.md) component integrated and pre-filled with the supported items.
The main application menu already has the [ADF Language Menu](https://www.alfresco.com/abn/adf/docs/core/language-menu.component/) component integrated and pre-filled with the supported items.
To change the default language set edit the `app.config.json` file and add or remove items:
@ -79,7 +80,7 @@ You can copy the content over to your newly created file and replace the English
The Content Application automatically bundles your file when the project builds.
You can test your locale by changing the browser language settings and reloading the page.
Optionally, you can extend the [ADF Language Menu](https://github.com/Alfresco/alfresco-ng2-components/blob/master/docs/core/language-menu.component.md) component with the newly added language by updating the `app.config.json` file.
Optionally, you can extend the [ADF Language Menu](https://www.alfresco.com/abn/adf/docs/core/language-menu.component/) component with the newly added language by updating the `app.config.json` file.
## Customizing ADF translations

View File

@ -1,4 +1,5 @@
---
Title: Navigation
---
# Navigation
@ -53,9 +54,7 @@ Navigation configuration supports array and object like schema. Defining an obje
`label` - represents the visual name of the link. It can be a string or a i18n defined reference.
<p class="danger">
Changing ` "route": { "url": "/..." } ` value will affect the navigation since these are mapped to application routing system.
</p>
**Caution:** Changing ` "route": { "url": "/..." } ` value will affect the navigation since these are mapped to application routing system.
### Custom text (i18n)

View File

@ -1,4 +1,5 @@
---
Title: Prerequisites
---
# Prerequisites
@ -9,9 +10,7 @@ This application uses the latest releases from Alfresco:
- [Alfresco Content Services (6.0)](https://www.alfresco.com/platform/content-services-ecm)
or [Alfresco Community Edition (6.0 - General Release: 201806)](https://www.alfresco.com/products/community/download)
<p class="warning">
You also need <a href="https://nodejs.org/en/" target="_blank">node.js</a> (LTS) installed to build it locally from source code.
</p>
**Note:** You also need [Node.js](https://nodejs.org/en/) (LTS) installed to build it locally from source code.
The latest version of the Alfresco Content platform is required
due to the application using the latest [REST APIs](https://docs.alfresco.com/5.2/pra/1/topics/pra-welcome.html) developments.

View File

@ -0,0 +1,59 @@
---
Title: Single Sign-On
---
# Single Sign-On
Besides Basic Authentication, you can use Content Application with:
- [Keycloak](https://www.keycloak.org/)
- [Alfresco Identity Service](https://docs.alfresco.com/identity1.0/concepts/identity-overview.html)
- Kerberos
The application contains reasonable defaults for Single Sign-On (aka SSO) setup.
You can find the settings in the `app.config.json` file, and they look similar to the following:
```json
{
"providers": "ECM",
"authType": "BASIC",
"oauth2": {
"host": "http://localhost:4200/auth/realms/alfresco",
"clientId": "alfresco",
"scope": "openid",
"secret": "",
"implicitFlow": true,
"silentLogin": true,
"redirectSilentIframeUri": "./assets/silent-refresh.html",
"redirectUri": "/",
"redirectUriLogout": "/logout"
}
}
```
To switch from Basic Authentication to SSO mode, change the `authType` property value to `OAUTH`.
Also, the default configuration assumes you have an `alfresco` client pre-configured.
You can experiment with authentication modes on the http://localhost:4200/#/settings page:
![Authentication Settings](../images/aca-sso-settings.png)
## Kerberos
To enable support for the additional Kerberos features
please enable the `withCredentials` flag in the `app.config.json` file:
```json
{
"auth": {
"withCredentials": true
}
}
```
Note that with the `withCredentials` flag enabled, the application is not going to redirect users to Login screen
as the login process is handled entirely by Kerberos.
## See also
For more details on the ADF Login component and configuration options please refer to the [Login](https://www.alfresco.com/abn/adf/docs/core/login.component/#single-sign-on-sso) documentation.

View File

@ -1,5 +1,5 @@
---
title: Get Help
Title: Get Help
---
# Where to get help

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View File

@ -1,4 +1,6 @@
---
Title: Tutorials
Github only: true
---
# Tutorials

View File

@ -1,4 +1,5 @@
---
Title: Custom route with parameters
---
# Custom route with parameters

View File

@ -1,4 +1,5 @@
---
Title: Dialog actions
---
# Dialog actions

View File

@ -1,6 +1,7 @@
---
Title: Introduction to extending ACA
---
# Introduction to extending the Alfresco Content Application
An introductory tutorial will appear here shortly.
Place holder for a future tutorial.

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -42,13 +42,15 @@ export class DataTable extends Component {
body: '.adf-datatable-body',
row: '.adf-datatable-row[role]',
selectedRow: '.adf-datatable-row.is-selected',
selectedRow: '.adf-datatable-row.adf-is-selected',
cell: '.adf-data-table-cell',
locationLink: '.aca-location-link',
nameLink: '.dl-link',
libraryRole: 'app-library-role-column',
nameLink: '.adf-datatable-link',
libraryRole: 'adf-library-role-column',
selectedIcon: '.mat-icon',
selectedIcon: '.mat-icon[class*="selected"]',
lockIcon: 'img[src*="lock"]',
lockOwner: '.aca-locked-by',
emptyListContainer: 'div.adf-no-content-container',
emptyFolderDragAndDrop: '.adf-empty-list_template .adf-empty-folder',
@ -60,9 +62,7 @@ export class DataTable extends Component {
head: ElementFinder = this.component.element(by.css(DataTable.selectors.head));
body: ElementFinder = this.component.element(by.css(DataTable.selectors.body));
cell = by.css(DataTable.selectors.cell);
locationLink = by.css(DataTable.selectors.locationLink);
nameLink: ElementFinder = browser.element(by.css(DataTable.selectors.nameLink));
emptyList: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListContainer));
emptyFolderDragAndDrop: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyFolderDragAndDrop));
emptyListTitle: ElementFinder = this.component.element(by.css(DataTable.selectors.emptyListTitle));
@ -94,7 +94,7 @@ export class DataTable extends Component {
return this.head.all(locator);
}
async getHeaderText() {
async getColumnHeadersText() {
const el = this.getColumnHeaders();
return await el.getText();
}
@ -157,12 +157,17 @@ export class DataTable extends Component {
return this.getRows().get(nth - 1);
}
getRowByName(name: string) {
getRowByName(name: string, location: string = '') {
if (location) {
return this.body.all(by.cssContainingText(DataTable.selectors.row, name))
.filter(async (elem) => await browser.isElementPresent(elem.element(by.cssContainingText(DataTable.selectors.cell, location))))
.first();
}
return this.body.element(by.cssContainingText(DataTable.selectors.row, name));
}
getRowFirstCell(name: string) {
return this.getRowByName(name).all(by.css(DataTable.selectors.cell)).get(0);
getRowFirstCell(name: string, location: string = '') {
return this.getRowByName(name, location).all(by.css(DataTable.selectors.cell)).get(0);
}
getRowNameCell(name: string) {
@ -177,8 +182,27 @@ export class DataTable extends Component {
return await this.getRowNameCellText(name).getAttribute('title');
}
async hasCheckMarkIcon(itemName: string) {
return await this.getRowByName(itemName).element(by.css(DataTable.selectors.selectedIcon)).isPresent();
async hasCheckMarkIcon(itemName: string, location: string = '') {
const row = this.getRowByName(itemName, location);
return await row.element(by.css(DataTable.selectors.selectedIcon)).isPresent();
}
async hasLockIcon(itemName: string, location: string = '') {
const row = this.getRowByName(itemName, location);
return await row.element(by.css(DataTable.selectors.lockIcon)).isPresent();
}
async hasLockOwnerInfo(itemName: string, location: string = '') {
const row = this.getRowByName(itemName, location);
return await row.element(by.css(DataTable.selectors.lockOwner)).isPresent();
}
async getLockOwner(itemName: string, location: string = '') {
if (await this.hasLockOwnerInfo(itemName, location)) {
const row = this.getRowByName(itemName, location);
return await row.$(DataTable.selectors.lockOwner).$('.locked_by--name').getText();
}
return '';
}
getNameLink(itemName: string) {
@ -191,15 +215,19 @@ export class DataTable extends Component {
// Navigation/selection methods
async doubleClickOnRowByName(name: string) {
const item = this.getRowFirstCell(name);
await Utils.waitUntilElementClickable(item);
await browser.actions().mouseMove(item).perform();
await browser.actions().click().click().perform();
try {
const item = this.getRowFirstCell(name);
await Utils.waitUntilElementClickable(item);
await browser.actions().mouseMove(item).perform();
await browser.actions().click().click().perform();
} catch (error) {
console.log('--- catch: doubleClickOnRowByName', error);
}
}
async selectItem(name: string) {
async selectItem(name: string, location: string = '') {
try{
const item = this.getRowFirstCell(name);
const item = this.getRowFirstCell(name, location);
await item.click();
} catch (e) {
@ -211,11 +239,11 @@ export class DataTable extends Component {
await this.getNameLink(itemName).click();
}
async selectMultipleItems(names: string[]) {
async selectMultipleItems(names: string[], location: string = '') {
await this.clearSelection();
await browser.actions().sendKeys(protractor.Key.COMMAND).perform();
for (const name of names) {
await this.selectItem(name);
await this.selectItem(name, location);
}
await browser.actions().sendKeys(protractor.Key.NULL).perform();
}
@ -225,7 +253,7 @@ export class DataTable extends Component {
const count = await this.countSelectedRows();
if (count !== 0) {
await browser.refresh();
await this.waitForHeader();
await this.wait();
}
} catch (error) {
console.log('------ clearSelection catch : ', error);
@ -238,13 +266,13 @@ export class DataTable extends Component {
}
async rightClickOnMultipleSelection() {
await this.waitForHeader();
await this.wait();
const itemFromSelection = this.getSelectedRows().get(0);
await browser.actions().click(itemFromSelection, protractor.Button.RIGHT).perform();
}
getItemLocationEl(name: string) {
return this.getRowByName(name).element(this.locationLink);
return this.getRowByName(name).element(by.css(DataTable.selectors.locationLink));
}
async getItemLocation(name: string) {
@ -252,10 +280,6 @@ export class DataTable extends Component {
}
async getItemLocationTooltip(name: string) {
return await this.getItemLocationEl(name).$('a').getAttribute('title');
}
async getItemLocationTileAttr(name: string) {
const location = this.getItemLocationEl(name).$('a');
const condition = () => location.getAttribute('title').then(value => value && value.length > 0);
@ -319,4 +343,31 @@ export class DataTable extends Component {
async getLibraryRole(name: string) {
return await this.getRowByName(name).element(by.css(DataTable.selectors.libraryRole)).getText();
}
async isItemPresent(name: string, location? : string) {
return await this.getRowByName(name, location).isPresent();
}
async getEntireDataTableText() {
return this.getRows().map((row) => {
return row.all(by.css(DataTable.selectors.cell)).map(async cell => await cell.getText());
});
}
async getSitesNameAndVisibility() {
const data = await this.getEntireDataTableText();
return data.reduce((acc, cell) => {
acc[cell[1]] = cell[3].toUpperCase();
return acc;
}, {});
}
async getSitesNameAndRole() {
const data = await this.getEntireDataTableText();
return data.reduce((acc, cell) => {
acc[cell[1]] = cell[2];
return acc;
}, {});
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -81,4 +81,47 @@ export class ConfirmDialog extends Component {
const button = this.getButtonByName(name);
return await button.isEnabled();
}
async isOkEnabled() {
return await this.isButtonEnabled('OK');
}
async isCancelEnabled() {
return await this.isButtonEnabled('Cancel');
}
async isKeepEnabled() {
return await this.isButtonEnabled('Keep');
}
async isDeleteEnabled() {
return await this.isButtonEnabled('Delete');
}
async isRemoveEnabled() {
return await this.isButtonEnabled('Remove');
}
async clickOk() {
return await this.clickButton('OK');
}
async clickCancel() {
return await this.clickButton('Cancel');
}
async clickKeep() {
return await this.clickButton('Keep');
}
async clickDelete() {
return await this.clickButton('Delete');
}
async clickRemove() {
return await this.clickButton('Remove');
}
}

View File

@ -3,7 +3,7 @@ import { Utils } from './../../utilities/utils';
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -39,7 +39,7 @@ export class CopyMoveDialog extends Component {
dataTable: '.adf-datatable-body',
row: '.adf-datatable-row[role]',
selectedRow: '.is-selected',
selectedRow: '.adf-is-selected',
button: '.mat-dialog-actions button'
};
@ -102,6 +102,13 @@ export class CopyMoveDialog extends Component {
return this.dataTable.element(by.cssContainingText('.adf-name-location-cell', folderName));
}
async doubleClickOnRow(name: string) {
const item = this.getRow(name);
await Utils.waitUntilElementClickable(item);
await browser.actions().mouseMove(item).perform();
await browser.actions().click().click().perform();
}
async selectLocation(location: 'Personal Files' | 'File Libraries') {
await this.locationDropDown.click();
await this.waitForDropDownToOpen();
@ -115,7 +122,7 @@ export class CopyMoveDialog extends Component {
await this.waitForDropDownToClose();
}
async chooseDestination(folderName: string) {
async selectDestination(folderName: string) {
const row = this.getRow(folderName);
await Utils.waitUntilElementClickable(row);
await row.click();

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,7 +23,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { ElementFinder, by, browser, protractor, ExpectedConditions as EC, promise } from 'protractor';
import { ElementFinder, by, browser, protractor, ExpectedConditions as EC } from 'protractor';
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
import { Component } from '../component';
import { Utils } from '../../utilities/utils';
@ -72,11 +72,39 @@ export class CreateOrEditFolderDialog extends Component {
return await this.validationMessage.isDisplayed();
}
async isUpdateButtonEnabled() {
return this.updateButton.isEnabled();
}
async isCreateButtonEnabled() {
return this.createButton.isEnabled();
}
async isCancelButtonEnabled() {
return this.cancelButton.isEnabled();
}
async isNameDisplayed() {
return await this.nameInput.isDisplayed();
}
async isDescriptionDisplayed() {
return await this.descriptionTextArea.isDisplayed();
}
async getValidationMessage() {
await this.isValidationMessageDisplayed();
return await this.validationMessage.getText();
}
async getName() {
return await this.nameInput.getAttribute('value');
}
async getDescription() {
return await this.descriptionTextArea.getAttribute('value');
}
async enterName(name: string) {
await this.nameInput.clear();
await Utils.typeInField(this.nameInput, name);
@ -104,4 +132,5 @@ export class CreateOrEditFolderDialog extends Component {
async clickUpdate() {
await this.updateButton.click();
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -30,7 +30,7 @@ import { Utils } from '../../utilities/utils';
export class CreateLibraryDialog extends Component {
private static selectors = {
root: 'app-library-dialog',
root: 'adf-library-dialog',
title: '.mat-dialog-title',
nameInput: 'input[placeholder="Name" i]',

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -37,7 +37,7 @@ export class ShareDialog extends Component {
label: '.adf-share-link__label',
shareToggle: `[data-automation-id='adf-share-toggle']`,
linkUrl: `[data-automation-id='adf-share-link']`,
inputAction: '.input-action',
inputAction: '.adf-input-action',
expireToggle: `[data-automation-id='adf-expire-toggle']`,
datetimePickerButton: '.mat-datetimepicker-toggle',
expirationInput: 'input[formcontrolname="time"]',
@ -94,6 +94,10 @@ export class ShareDialog extends Component {
return await this.url.getAttribute('readonly');
}
async isCloseEnabled() {
return await this.closeButton.isEnabled();
}
async clickClose() {
await this.closeButton.click();
await this.waitForDialogToClose();

View File

@ -0,0 +1,121 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2019 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';
import { Utils } from '../../utilities/utils';
export class UploadNewVersionDialog extends Component {
private static selectors = {
root: '.aca-node-version-upload-dialog',
title: '.mat-dialog-title',
content: '.mat-dialog-content',
button: '.mat-button',
radioButton: `.mat-radio-label`,
descriptionTextArea: 'textarea'
};
title: ElementFinder = this.component.element(by.css(UploadNewVersionDialog.selectors.title));
content: ElementFinder = this.component.element(by.css(UploadNewVersionDialog.selectors.content));
cancelButton: ElementFinder = this.component.element(by.cssContainingText(UploadNewVersionDialog.selectors.button, 'Cancel'));
uploadButton: ElementFinder = this.component.element(by.cssContainingText(UploadNewVersionDialog.selectors.button, 'Upload'));
majorOption: ElementFinder = this.component.element(by.cssContainingText(UploadNewVersionDialog.selectors.radioButton, 'Major'));
minorOption: ElementFinder = this.component.element(by.cssContainingText(UploadNewVersionDialog.selectors.radioButton, 'Minor'));
description: ElementFinder = this.component.element(by.css(UploadNewVersionDialog.selectors.descriptionTextArea));
constructor(ancestor?: ElementFinder) {
super(UploadNewVersionDialog.selectors.root, ancestor);
}
async waitForDialogToClose() {
return await browser.wait(EC.stalenessOf(this.title), BROWSER_WAIT_TIMEOUT);
}
async isDialogOpen() {
return await browser.$(UploadNewVersionDialog.selectors.root).isDisplayed();
}
async getTitle() {
return await this.title.getText();
}
async getText() {
return await this.content.getText();
}
async isDescriptionDisplayed() {
return await this.description.isDisplayed();
}
async isMinorOptionDisplayed() {
return await this.minorOption.isDisplayed();
}
async isMajorOptionDisplayed() {
return await this.majorOption.isDisplayed();
}
async isCancelButtonEnabled() {
return this.cancelButton.isEnabled();
}
async isUploadButtonEnabled() {
return this.uploadButton.isEnabled();
}
async clickCancel() {
await this.cancelButton.click();
await this.waitForDialogToClose();
}
async clickUpload() {
await this.uploadButton.click();
await this.waitForDialogToClose();
}
async clickMajor() {
return await this.majorOption.click();
}
async clickMinor() {
return await this.minorOption.click();
}
async enterDescription(description: string) {
await this.description.clear();
await Utils.typeInField(this.description, description);
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,25 +23,31 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { ElementFinder, by, browser } from 'protractor';
import { ElementFinder, by, browser, until } from 'protractor';
import { Component } from '../component';
import { UserInfo } from './user-info';
import { Menu } from '../menu/menu';
import { Toolbar } from './../toolbar/toolbar';
import { SearchInput } from '../search/search-input';
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
export class Header extends Component {
private locators = {
private static selectors = {
root: 'app-header',
logoLink: by.css('.app-menu__title'),
userInfo: by.css('aca-current-user'),
moreActions: by.id('app.header.more')
moreActions: by.id('app.header.more'),
sidenavToggle: `[id='adf-sidebar-toggle-start']`,
expandedSidenav: by.css(`[data-automation-id='expanded']`),
collapsedSidenav: by.css(`[data-automation-id='collapsed']`)
};
logoLink: ElementFinder = this.component.element(this.locators.logoLink);
userInfo: UserInfo = new UserInfo(this.component);
moreActions: ElementFinder = browser.element(this.locators.moreActions);
logoLink: ElementFinder = this.component.element(Header.selectors.logoLink);
moreActions: ElementFinder = browser.element(Header.selectors.moreActions);
sidenavToggle: ElementFinder = this.component.element(by.css(Header.selectors.sidenavToggle));
userInfo: UserInfo = new UserInfo(this.component);
menu: Menu = new Menu();
toolbar: Toolbar = new Toolbar();
searchInput: SearchInput = new SearchInput();
@ -54,5 +60,34 @@ export class Header extends Component {
await this.moreActions.click();
await this.menu.waitForMenuToOpen();
}
async isSignOutDisplayed() {
return await this.userInfo.menu.isMenuItemPresent('Sign out');
}
async clickSidenavToggle() {
await this.sidenavToggle.click();
}
async isExpandedSidenav() {
return await browser.isElementPresent(Header.selectors.expandedSidenav);
}
async expandSideNav() {
const expanded = await this.isExpandedSidenav();
if ( !expanded ) {
await this.clickSidenavToggle();
await browser.wait(until.elementLocated(Header.selectors.expandedSidenav), BROWSER_WAIT_TIMEOUT, '--- timeout waiting for expanded sidenav' );
}
}
async collapseSideNav() {
const expanded = await this.isExpandedSidenav();
if ( expanded ) {
await this.clickSidenavToggle();
await browser.wait(until.elementLocated(Header.selectors.collapsedSidenav), BROWSER_WAIT_TIMEOUT, '--- timeout waiting for collapsed sidenav')
}
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -28,14 +28,14 @@ import { Menu } from '../menu/menu';
import { Component } from '../component';
export class UserInfo extends Component {
private locators = {
private static selectors = {
avatar: by.css('.current-user__avatar'),
fullName: by.css('.current-user__full-name'),
menuItems: by.css('[mat-menu-item]')
};
fullName: ElementFinder = this.component.element(this.locators.fullName);
avatar: ElementFinder = this.component.element(this.locators.avatar);
fullName: ElementFinder = this.component.element(UserInfo.selectors.fullName);
avatar: ElementFinder = this.component.element(UserInfo.selectors.avatar);
menu: Menu = new Menu();

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,10 +23,9 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { ElementFinder, ElementArrayFinder, by, browser, ExpectedConditions as EC } from 'protractor';
import { ElementFinder, ElementArrayFinder, by, browser, ExpectedConditions as EC, until } from 'protractor';
import { Component } from '../component';
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
import { Utils } from './../../utilities/utils';
export class InfoDrawer extends Component {
private static selectors = {
@ -45,6 +44,19 @@ export class InfoDrawer extends Component {
headerTitle: '.adf-info-drawer-layout-header-title',
// comments tab
commentsContainer: '.adf-comments-container',
commentsHeader: '.adf-comments-header',
commentsTextArea: '.adf-comments-input-container textarea',
addCommentButton: 'button.adf-comments-input-add',
commentsList: '.adf-comment-list',
commentsListItem: '.adf-comment-list-item',
commentById: `adf-comment-`,
commentUserName: 'comment-user',
commentUserAvatar: 'comment-user-icon',
commentMessage: 'comment-message',
commentTime: 'comment-time',
// metadata card
metadataTabContent: '.app-metadata-tab .mat-card-content',
metadataTabAction: '.app-metadata-tab .mat-card-actions .mat-button',
@ -66,6 +78,19 @@ export class InfoDrawer extends Component {
tabActiveContent: ElementFinder = this.component.element(by.css(InfoDrawer.selectors.activeTabContent));
commentsContainer: ElementFinder = this.component.element(by.css(InfoDrawer.selectors.commentsContainer));
commentsHeader: ElementFinder = this.component.element(by.css(InfoDrawer.selectors.commentsHeader));
commentTextarea: ElementFinder = this.component.element(by.css(InfoDrawer.selectors.commentsTextArea));
addCommentButton: ElementFinder = this.component.element(by.css(InfoDrawer.selectors.addCommentButton));
commentsList: ElementArrayFinder = this.component.all(by.css(InfoDrawer.selectors.commentsListItem));
commentListItem = by.css(InfoDrawer.selectors.commentsListItem);
commentUserAvatar = by.id(InfoDrawer.selectors.commentUserAvatar);
commentUser = by.id(InfoDrawer.selectors.commentUserName)
commentText = by.id(InfoDrawer.selectors.commentMessage);
commentTime = by.id(InfoDrawer.selectors.commentTime);
nextButton: ElementFinder = this.component.element(by.css(InfoDrawer.selectors.next));
previousButton: ElementFinder = this.component.element(by.css(InfoDrawer.selectors.previous));
@ -86,6 +111,7 @@ export class InfoDrawer extends Component {
super(InfoDrawer.selectors.root, ancestor);
}
async waitForInfoDrawerToOpen() {
return await browser.wait(EC.presenceOf(this.header), BROWSER_WAIT_TIMEOUT);
}
@ -95,28 +121,39 @@ export class InfoDrawer extends Component {
}
async isEmpty() {
if (await browser.isElementPresent(by.css(InfoDrawer.selectors.tabs))) {
return false;
}
return true;
return !(await browser.isElementPresent(by.css(InfoDrawer.selectors.tabs)));
}
async waitForCommentsTabContainer() {
await browser.wait(EC.visibilityOf(this.commentsContainer), BROWSER_WAIT_TIMEOUT);
}
getTabByTitle(title: string) {
return this.component.element(by.cssContainingText(InfoDrawer.selectors.tabLabel, title));
}
async getTabsCount() {
return await this.component.all(by.css(InfoDrawer.selectors.tabLabel)).count();
}
async isTabPresent(title: string) {
return await this.getTabByTitle(title).isPresent();
}
async isTabDisplayed(title: string) {
return await this.getTabByTitle(title).isDisplayed();
if (await browser.isElementPresent(this.getTabByTitle(title))) {
return await this.getTabByTitle(title).isDisplayed();
}
}
async getTabTitle(index: number) {
return await this.tabLabelsList.get(index - 1).getAttribute('innerText');
}
async getActiveTabTitle() {
return await this.tabActiveLabel.getText();
}
async clickTab(title: string) {
await this.getTabByTitle(title).click();
}
@ -146,12 +183,6 @@ export class InfoDrawer extends Component {
return this.getFieldByName(fieldName).isEnabled();
}
async isVisibilityEnabled() {
const wrapper = this.getLabelWrapper('Visibility');
const field = wrapper.element(by.xpath('..')).element(by.css(InfoDrawer.selectors.dropDown));
return await field.isEnabled();
}
async getValueOfField(fieldName: string) {
return await this.getFieldByName(fieldName).getText();
}
@ -162,11 +193,6 @@ export class InfoDrawer extends Component {
return await input.sendKeys(text);
}
async typeTextInInput(fieldName: string, text: string) {
const input = this.getFieldByName(fieldName);
await input.clear();
return await Utils.typeInField(input, text);
}
getButton(button: string) {
return this.component.element(by.cssContainingText(InfoDrawer.selectors.metadataTabAction, button));
@ -184,15 +210,49 @@ export class InfoDrawer extends Component {
return await this.getButton(button).click();
}
async isButtonDisabled(button: string) {
async waitForVisibilityDropDownToOpen() {
await browser.wait(EC.presenceOf(this.visibilityDropDown), BROWSER_WAIT_TIMEOUT);
}
async waitForVisibilityDropDownToClose() {
await browser.wait(EC.stalenessOf(browser.$('.mat-option .mat-option-text')), BROWSER_WAIT_TIMEOUT);
}
// ---------------
async isAboutTabDisplayed() {
return await this.isTabDisplayed('About');
}
async isPropertiesTabDisplayed() {
return await this.isTabDisplayed('Properties');
}
async isCommentsTabDisplayed() {
return await this.isTabDisplayed('Comments');
}
async clickCommentsTab() {
try {
const disabled = await this.getButton(button).getAttribute('disabled');
return disabled;
await this.getTabByTitle('Comments').click();
await this.waitForCommentsTabContainer();
await browser.wait(EC.visibilityOf(this.addCommentButton), BROWSER_WAIT_TIMEOUT);
} catch (error) {
console.log('----- isButtonDisabled catch: ', error);
console.error('--- catch error on clickCommentsTab ---');
throw error;
}
}
async clickAboutTab() {
try {
return await this.getTabByTitle('About').click();
} catch (error) {
console.error('--- catch error on clickAboutTab ---');
}
}
async isMessageDisplayed() {
return await browser.isElementPresent(this.hint);
}
@ -210,80 +270,59 @@ export class InfoDrawer extends Component {
}
// ---------------
async isNameDisplayed() {
return await this.isFieldDisplayed('Name');
}
async isDescriptionDisplayed() {
return await this.isFieldDisplayed('Description');
}
async isVisibilityDisplayed() {
return await this.isFieldDisplayed('Visibility');
}
async isLibraryIdDisplayed() {
return await this.isFieldDisplayed('Library ID');
}
async getName() {
return await this.getValueOfField('Name');
}
async getVisibility() {
return await this.getValueOfField('Visibility');
}
async getLibraryId() {
return await this.getValueOfField('Library ID');
}
async getDescription() {
return await this.getValueOfField('Description');
}
async isNameEnabled() {
return await this.isInputEnabled('Name');
}
async isLibraryIdEnabled() {
return await this.isInputEnabled('Library ID');
}
async isDescriptionEnabled() {
return await this.isInputEnabled('Description');
async getName() {
return await this.getValueOfField('Name');
}
async enterName(name: string) {
return await this.enterTextInInput('Name', name);
}
async typeName(name: string) {
return await this.typeTextInInput('Name', name);
async isDescriptionDisplayed() {
return await this.isFieldDisplayed('Description');
}
async isDescriptionEnabled() {
return await this.isInputEnabled('Description');
}
async getDescription() {
return await this.getValueOfField('Description');
}
async enterDescription(desc: string) {
return await this.enterTextInInput('Description', desc);
}
async typeDescription(desc: string) {
return await this.typeTextInInput('Description', desc);
async isVisibilityEnabled() {
const wrapper = this.getLabelWrapper('Visibility');
const field = wrapper.element(by.xpath('..')).element(by.css(InfoDrawer.selectors.dropDown));
return await field.isEnabled();
}
async waitForDropDownToOpen() {
await browser.wait(EC.presenceOf(this.visibilityDropDown), BROWSER_WAIT_TIMEOUT);
async isVisibilityDisplayed() {
return await this.isFieldDisplayed('Visibility');
}
async waitForDropDownToClose() {
await browser.wait(EC.stalenessOf(browser.$('.mat-option .mat-option-text')), BROWSER_WAIT_TIMEOUT);
async getVisibility() {
return await this.getValueOfField('Visibility');
}
async setVisibility(visibility: string) {
const val = visibility.toLowerCase();
await this.visibilityDropDown.click();
await this.waitForDropDownToOpen();
await this.waitForVisibilityDropDownToOpen();
if (val === 'public') {
await this.visibilityPublic.click();
@ -295,8 +334,130 @@ export class InfoDrawer extends Component {
console.log('----- invalid visibility', val);
}
await this.waitForDropDownToClose();
await this.waitForVisibilityDropDownToClose();
}
async isLibraryIdDisplayed() {
return await this.isFieldDisplayed('Library ID');
}
async isLibraryIdEnabled() {
return await this.isInputEnabled('Library ID');
}
async getLibraryId() {
return await this.getValueOfField('Library ID');
}
async isEditEnabled() {
return await this.isButtonEnabled('Edit');
}
async isEditDisplayed() {
return await this.isButtonDisplayed('Edit');
}
async clickEdit() {
return await this.clickButton('Edit');
}
async isUpdateEnabled() {
return await this.isButtonEnabled('Update');
}
async isUpdateDisplayed() {
return await this.isButtonDisplayed('Update');
}
async clickUpdate() {
return await this.clickButton('Update');
}
async isCancelEnabled() {
return await this.isButtonEnabled('Cancel');
}
async isCancelDisplayed() {
return await this.isButtonDisplayed('Cancel');
}
async clickCancel() {
return await this.clickButton('Cancel');
}
async getCommentsTabHeaderText() {
return await this.commentsHeader.getText();
}
async isCommentTextAreaDisplayed() {
return await browser.isElementPresent(this.commentTextarea);
}
async isAddCommentButtonEnabled() {
const present = await browser.isElementPresent(this.addCommentButton);
if (present) {
return await this.addCommentButton.isEnabled();
}
return false;
}
async getCommentListItem() {
return await browser.wait(until.elementLocated(this.commentListItem), BROWSER_WAIT_TIMEOUT / 2);
}
async getCommentById(commentId?: string) {
if (commentId) {
return await browser.wait(until.elementLocated(by.id(`${InfoDrawer.selectors.commentById}${commentId}`)), BROWSER_WAIT_TIMEOUT / 2);
}
return await this.getCommentListItem();
}
async isCommentDisplayed(commentId?: string) {
return await browser.isElementPresent(await this.getCommentById(commentId));
}
async isCommentUserAvatarDisplayed(commentId?: string) {
const commentElement = await this.getCommentById(commentId);
return await browser.isElementPresent(commentElement.findElement(this.commentUserAvatar));
}
async getCommentText(commentId?: string) {
const commentElement = await this.getCommentById(commentId);
const message = await commentElement.findElement(this.commentText);
return await message.getText();
}
async getCommentUserName(commentId?: string) {
const commentElement = await this.getCommentById(commentId);
const user = await commentElement.findElement(this.commentUser);
return await user.getText();
}
async getCommentTime(commentId?: string) {
const commentElement = await this.getCommentById(commentId);
const time = await commentElement.findElement(this.commentTime);
return await time.getText();
}
async getNthCommentId(index: number) {
return await this.commentsList.get(index - 1).getAttribute('id');
}
async typeComment(text: string) {
return await this.commentTextarea.sendKeys(text);
}
async clickAddButton() {
return await this.addCommentButton.click();
}
async getCommentTextFromTextArea() {
return await this.commentTextarea.getAttribute('value');
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -27,26 +27,26 @@ import { by, ElementFinder } from 'protractor';
import { Component } from '../component';
export class LoginComponent extends Component {
static selector = 'adf-login';
private static selectors = {
root: 'adf-login',
private locators = {
usernameInput: by.css('input#username'),
passwordInput: by.css('input#password'),
passwordVisibility: by.css('.adf-login-password-icon'),
submitButton: by.css('button#login-button'),
errorMessage: by.css('.login-error-message'),
copyright: by.css('.copyright')
errorMessage: by.css('.adf-login-error-message'),
copyright: by.css('.adf-copyright')
};
usernameInput: ElementFinder = this.component.element(this.locators.usernameInput);
passwordInput: ElementFinder = this.component.element(this.locators.passwordInput);
submitButton: ElementFinder = this.component.element(this.locators.submitButton);
errorMessage: ElementFinder = this.component.element(this.locators.errorMessage);
copyright: ElementFinder = this.component.element(this.locators.copyright);
passwordVisibility: ElementFinder = this.component.element(this.locators.passwordVisibility);
usernameInput: ElementFinder = this.component.element(LoginComponent.selectors.usernameInput);
passwordInput: ElementFinder = this.component.element(LoginComponent.selectors.passwordInput);
submitButton: ElementFinder = this.component.element(LoginComponent.selectors.submitButton);
errorMessage: ElementFinder = this.component.element(LoginComponent.selectors.errorMessage);
copyright: ElementFinder = this.component.element(LoginComponent.selectors.copyright);
passwordVisibility: ElementFinder = this.component.element(LoginComponent.selectors.passwordVisibility);
constructor(ancestor?: ElementFinder) {
super(LoginComponent.selector, ancestor);
super(LoginComponent.selectors.root, ancestor);
}
async enterUsername(username: string) {
@ -72,6 +72,10 @@ export class LoginComponent extends Component {
return this.submitButton.click();
}
async clickPasswordVisibility() {
return await this.passwordVisibility.click();
}
async getPasswordVisibility() {
const text = await this.passwordVisibility.getText();
if (text.endsWith('visibility_off')) {
@ -84,7 +88,7 @@ export class LoginComponent extends Component {
}
}
async isPasswordShown() {
async isPasswordDisplayed() {
const type = await this.passwordInput.getAttribute('type');
if (type === 'text') {
return true;
@ -95,4 +99,21 @@ export class LoginComponent extends Component {
}
}
}
async isUsernameEnabled() {
return await this.usernameInput.isEnabled();
}
async isPasswordEnabled() {
return await this.passwordInput.isEnabled();
}
async isSubmitEnabled() {
return await this.submitButton.isEnabled();
}
async isPasswordHidden() {
return !(await this.getPasswordVisibility());
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -37,7 +37,11 @@ export class Menu extends Component {
submenu: 'app-context-menu-item .mat-menu-item',
share: `[data-automation-id='share-action-button']`
editFolder: `.mat-menu-item[id$='editFolder']`,
favoriteAction: `.mat-menu-item[id$='favorite.add']`,
removeFavoriteAction: `.mat-menu-item[id$='favorite.remove']`,
editOffline: `.mat-menu-item[title='Edit offline']`,
cancelEditing: `.mat-menu-item[title='Cancel editing']`
};
items: ElementArrayFinder = this.component.all(by.css(Menu.selectors.item));
@ -45,8 +49,33 @@ export class Menu extends Component {
uploadFiles: ElementFinder = browser.element(by.id(Menu.selectors.uploadFiles));
submenus: ElementArrayFinder = browser.element.all(by.css(Menu.selectors.submenu));
shareAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.share, 'Share'));
shareEditAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.share, 'Shared link settings'));
cancelEditingAction: ElementFinder = this.component.element(by.css(Menu.selectors.cancelEditing));
cancelJoinAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Cancel join'));
copyAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Copy'));
createFolderAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Create folder'));
createLibraryAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Create Library'));
deleteAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Delete'));
downloadAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Download'));
editFolderAction: ElementFinder = this.component.element(by.css(Menu.selectors.editFolder));
editOfflineAction: ElementFinder = this.component.element(by.css(Menu.selectors.editOffline));
favoriteAction: ElementFinder = this.component.element(by.css(Menu.selectors.favoriteAction));
removeFavoriteAction: ElementFinder = this.component.element(by.css(Menu.selectors.removeFavoriteAction));
toggleFavoriteAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Favorite'));
toggleRemoveFavoriteAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Remove favorite'));
joinAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Join'));
leaveAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Leave'));
managePermissionsAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Permissions'));
manageVersionsAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Manage Versions'));
uploadNewVersionAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Upload new version'));
moveAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Move'));
permanentDeleteAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Permanently delete'));
restoreAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Restore'));
shareAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Share'));
shareEditAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Shared link settings'));
uploadFileAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Upload file'));
uploadFolderAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'Upload folder'));
viewAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'View'));
viewDetailsAction: ElementFinder = this.component.element(by.cssContainingText(Menu.selectors.item, 'View details'));
constructor(ancestor?: ElementFinder) {
super(Menu.selectors.root, ancestor);
@ -173,13 +202,161 @@ export class Menu extends Component {
return this.uploadFiles;
}
async clickShareAction() {
async clickEditFolder() {
return await this.editFolderAction.click();
}
async clickShare() {
const action = this.shareAction;
await action.click();
}
async clickShareEditAction() {
async clickSharedLinkSettings() {
const action = this.shareEditAction;
await action.click();
}
async isViewPresent() {
return await this.viewAction.isPresent();
}
async isDownloadPresent() {
return await this.downloadAction.isPresent();
}
async isEditFolderPresent() {
return await this.editFolderAction.isPresent();
}
async isEditOfflinePresent() {
return await this.editOfflineAction.isPresent();
}
async isCancelEditingPresent() {
return await this.cancelEditingAction.isPresent();
}
async isCopyPresent() {
return await this.copyAction.isPresent();
}
async isMovePresent() {
return await this.moveAction.isPresent();
}
async isDeletePresent() {
return await this.deleteAction.isPresent();
}
async isManagePermissionsPresent() {
return await this.managePermissionsAction.isPresent();
}
async isManageVersionsPresent() {
return await this.manageVersionsAction.isPresent();
}
async isUploadNewVersionPresent() {
return await this.uploadNewVersionAction.isPresent();
}
async isFavoritePresent() {
return await this.favoriteAction.isPresent();
}
async isRemoveFavoritePresent() {
return await this.removeFavoriteAction.isPresent();
}
async isToggleFavoritePresent() {
return await this.toggleFavoriteAction.isPresent();
}
async isToggleRemoveFavoritePresent() {
return await this.toggleRemoveFavoriteAction.isPresent();
}
async isJoinLibraryPresent() {
return await this.joinAction.isPresent();
}
async isCancelJoinPresent() {
return await this.cancelJoinAction.isPresent();
}
async isLeaveLibraryPresent() {
return await this.leaveAction.isPresent();
}
async isPermanentDeletePresent() {
return await this.permanentDeleteAction.isPresent();
}
async isRestorePresent() {
return await this.restoreAction.isPresent();
}
async isSharePresent() {
return await this.shareAction.isPresent();
}
async isSharedLinkSettingsPresent() {
return await this.shareEditAction.isPresent();
}
async isViewDetailsPresent() {
return await this.viewDetailsAction.isPresent();
}
async isCreateFolderPresent() {
return await this.createFolderAction.isPresent();
}
async isCreateFolderEnabled() {
return await this.createFolderAction.isEnabled();
}
async isCreateLibraryPresent() {
return await this.createLibraryAction.isPresent();
}
async isCreateLibraryEnabled() {
return await this.createLibraryAction.isEnabled();
}
async isUploadFilePresent() {
return await this.uploadFileAction.isPresent();
}
async isUploadFileEnabled() {
return await this.uploadFileAction.isEnabled();
}
async isUploadFolderPresent() {
return await this.uploadFolderAction.isPresent();
}
async isUploadFolderEnabled() {
return await this.uploadFolderAction.isEnabled();
}
async clickCreateFolder() {
const action = this.createFolderAction;
await action.click();
}
async clickCreateLibrary() {
const action = this.createLibraryAction;
await action.click();
}
async clickUploadFile() {
const action = this.uploadFileAction;
await action.click();
}
async clickUploadFolder() {
const action = this.uploadFolderAction;
await action.click();
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -26,7 +26,7 @@
import { ElementFinder, by } from 'protractor';
import { Menu } from '../menu/menu';
import { Component } from '../component';
import { browser } from 'protractor';
export class Pagination extends Component {
private static selectors = {
root: 'adf-pagination',
@ -61,7 +61,6 @@ export class Pagination extends Component {
await maxItemsButton.click();
await menu.waitForMenuToOpen();
// return menu;
}
async openCurrentPageMenu() {
@ -69,11 +68,6 @@ export class Pagination extends Component {
await pagesButton.click();
await menu.waitForMenuToOpen();
// return menu;
}
async getText(elem: ElementFinder) {
return await elem.getText();
}
async resetToDefaultPageSize() {
@ -95,4 +89,56 @@ export class Pagination extends Component {
async clickPrevious() {
await this.previousButton.click();
}
async isNextEnabled() {
return await this.nextButton.isEnabled();
}
async isPreviousEnabled() {
return await this.previousButton.isEnabled();
}
async isPagesButtonPresent() {
return await browser.isElementPresent(this.pagesButton);
}
async isRangePresent() {
return await this.range.isPresent();
}
async isMaxItemsPresent() {
return await this.maxItems.isPresent();
}
async isCurrentPagePresent() {
return await this.currentPage.isPresent();
}
async isTotalPagesPresent() {
return await this.totalPages.isPresent();
}
async isPreviousButtonPresent() {
return await this.previousButton.isPresent();
}
async isNextButtonPresent() {
return await this.nextButton.isPresent();
}
async getCurrentPage() {
return await this.currentPage.getText();
}
async getRange() {
return await this.range.getText();
}
async getMaxItems() {
return await this.maxItems.getText();
}
async getTotalPages() {
return await this.totalPages.getText();
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,9 +23,10 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { ElementFinder, browser, by, until, protractor } from 'protractor';
import { ElementFinder, browser, by, until, protractor, ExpectedConditions as EC } from 'protractor';
import { BROWSER_WAIT_TIMEOUT } from '../../configs';
import { Component } from '../component';
import { Utils } from '../../utilities/utils';
export class SearchInput extends Component {
private static selectors = {
@ -35,27 +36,36 @@ export class SearchInput extends Component {
searchControl: '.app-search-control',
searchInput: 'app-control-input',
searchOptionsArea: 'search-options',
optionCheckbox: '.mat-checkbox'
optionCheckbox: '.mat-checkbox',
clearButton: '.app-clear-icon'
};
searchButton: ElementFinder = this.component.element(by.css(SearchInput.selectors.searchButton));
searchContainer: ElementFinder = browser.element(by.css(SearchInput.selectors.searchContainer));
searchControl: ElementFinder = browser.element(by.css(SearchInput.selectors.searchControl));
searchBar: ElementFinder = browser.element(by.id(SearchInput.selectors.searchInput));
searchOptionsArea: ElementFinder = browser.element(by.id(SearchInput.selectors.searchOptionsArea));
searchFilesOption: ElementFinder = this.searchOptionsArea.element(by.cssContainingText(SearchInput.selectors.optionCheckbox, 'Files'));
searchFoldersOption: ElementFinder = this.searchOptionsArea.element(by.cssContainingText(SearchInput.selectors.optionCheckbox, 'Folders'));
searchLibrariesOption: ElementFinder = this.searchOptionsArea.element(by.cssContainingText(SearchInput.selectors.optionCheckbox, 'Libraries'));
clearSearchButton: ElementFinder = this.searchContainer.$(SearchInput.selectors.clearButton);
constructor(ancestor?: ElementFinder) {
super(SearchInput.selectors.root, ancestor);
}
async waitForSearchControl() {
return await browser.wait(EC.presenceOf(this.searchControl), BROWSER_WAIT_TIMEOUT, '--- timeout waitForSearchControl ---');
}
async isSearchContainerDisplayed() {
return (await this.searchContainer.isDisplayed()) && (await this.searchButton.isDisplayed());
}
async clickSearchButton() {
await Utils.waitUntilElementClickable(this.searchButton);
await this.searchButton.click();
await this.waitForSearchControl();
}
async isOptionsAreaDisplayed() {
@ -64,14 +74,17 @@ export class SearchInput extends Component {
}
async clickFilesOption() {
await browser.wait(EC.elementToBeClickable(this.searchFilesOption), BROWSER_WAIT_TIMEOUT, '--- timeout waiting for Files to be clickable');
return await this.searchFilesOption.click();
}
async clickFoldersOption() {
await browser.wait(EC.elementToBeClickable(this.searchFoldersOption), BROWSER_WAIT_TIMEOUT, '--- timeout waiting for Folders to be clickable');
return await this.searchFoldersOption.click();
}
async clickLibrariesOption() {
await browser.wait(EC.elementToBeClickable(this.searchLibrariesOption), BROWSER_WAIT_TIMEOUT, '--- timeout waiting for Libraries to be clickable');
return await this.searchLibrariesOption.click();
}
@ -117,6 +130,16 @@ export class SearchInput extends Component {
}
}
async isClearSearchButtonPresent() {
return await browser.isElementPresent(this.clearSearchButton);
}
async clickClearSearchButton() {
if (await this.isClearSearchButtonPresent()) {
return await this.clearSearchButton.click();
}
}
async checkOnlyFiles() {
await this.clearOptions();
await this.clickFilesOption();
@ -139,8 +162,14 @@ export class SearchInput extends Component {
}
async searchFor(text: string) {
await browser.wait(EC.elementToBeClickable(this.searchBar), BROWSER_WAIT_TIMEOUT, '---- timeout waiting for searchBar to be clickable');
await this.searchBar.clear();
await this.searchBar.sendKeys(text);
await this.searchBar.sendKeys(protractor.Key.ENTER);
}
async searchForTextAndCloseSearchOptions(text: string) {
await this.searchFor(text);
await Utils.pressEscape();
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,8 +23,8 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { ElementFinder, ElementArrayFinder, by, element } from 'protractor';
import { SIDEBAR_LABELS } from '../../configs';
import { ElementFinder, ElementArrayFinder, by, element, browser } from 'protractor';
import { SIDEBAR_LABELS, BROWSER_WAIT_TIMEOUT } from '../../configs';
import { Menu } from '../menu/menu';
import { Component } from '../component';
import { Utils } from '../../utilities/utils';
@ -36,15 +36,35 @@ export class Sidenav extends Component {
label: '.item--label',
expansion_panel: ".mat-expansion-panel-header",
expansion_panel_content: ".mat-expansion-panel-body",
active: 'item--active',
activeLink: '.item--active',
newButton: '[data-automation-id="create-button"]'
active: 'mat-accent',
activeClass: '.item--active',
activeChild: 'item--active',
newButton: '[data-automation-id="create-button"]',
personalFiles: `[data-automation-id='app.navbar.personalFiles']`,
fileLibraries: `[data-automation-id='app.navbar.libraries.menu']`,
myLibraries: `[data-automation-id='app.navbar.libraries.files']`,
favoriteLibraries: `[data-automation-id='app.navbar.libraries.favorite']`,
shared: `[data-automation-id='app.navbar.shared']`,
recentFiles: `[data-automation-id='app.navbar.recentFiles']`,
favorites: `[data-automation-id='app.navbar.favorites']`,
trash: `[data-automation-id='app.navbar.trashcan']`
};
links: ElementArrayFinder = this.component.all(by.css(Sidenav.selectors.link));
activeLink: ElementFinder = this.component.element(by.css(Sidenav.selectors.activeLink));
activeLink: ElementFinder = this.component.element(by.css(Sidenav.selectors.activeClass));
newButton: ElementArrayFinder = this.component.all(by.css(Sidenav.selectors.newButton));
personalFiles: ElementFinder = this.component.element(by.css(Sidenav.selectors.personalFiles));
fileLibraries: ElementFinder = this.component.element(by.css(Sidenav.selectors.fileLibraries));
myLibraries: ElementFinder = browser.element(by.css(Sidenav.selectors.myLibraries));
favoriteLibraries: ElementFinder = browser.element(by.css(Sidenav.selectors.favoriteLibraries));
shared: ElementFinder = this.component.element(by.css(Sidenav.selectors.shared));
recentFiles: ElementFinder = this.component.element(by.css(Sidenav.selectors.recentFiles));
favorites: ElementFinder = this.component.element(by.css(Sidenav.selectors.favorites));
trash: ElementFinder = this.component.element(by.css(Sidenav.selectors.trash));
menu: Menu = new Menu();
constructor(ancestor?: ElementFinder) {
@ -86,13 +106,12 @@ export class Sidenav extends Component {
}
async isActive(name: string) {
const className = await this.getLinkLabel(name).getAttribute('class');
return className.includes(Sidenav.selectors.active);
return await this.getLinkLabel(name).isElementPresent(by.css(Sidenav.selectors.activeClass));
}
async childIsActive(name: string) {
const childClass = await this.getLinkLabel(name).element(by.css('span')).getAttribute('class');
return childClass.includes(Sidenav.selectors.active);
return childClass.includes(Sidenav.selectors.activeChild);
}
getLink(name: string) {
@ -100,7 +119,17 @@ export class Sidenav extends Component {
}
getLinkLabel(name: string) {
return this.component.element(by.cssContainingText(Sidenav.selectors.label, name));
switch (name) {
case 'Personal Files': return this.personalFiles;
case 'File Libraries': return this.fileLibraries;
case 'My Libraries': return this.myLibraries;
case 'Favorite Libraries': return this.favoriteLibraries;
case 'Shared': return this.shared;
case 'Recent Files': return this.recentFiles;
case 'Favorites': return this.favorites;
case 'Trash': return this.trash;
default: return this.personalFiles;
}
}
getActiveLink() {
@ -108,17 +137,25 @@ export class Sidenav extends Component {
}
async getLinkTooltip(name: string) {
return await this.getLink(name).getAttribute('title');
const link = this.getLinkLabel(name);
const condition = () => link.getAttribute('title').then(value => value && value.length > 0);
await browser.actions().mouseMove(link).perform();
await browser.wait(condition, BROWSER_WAIT_TIMEOUT);
return await link.getAttribute('title');
}
async navigateToLink(name: string) {
async clickLink(name: string) {
try{
const link = this.getLinkLabel(name);
await Utils.waitUntilElementClickable(link);
return await link.click();
} catch (e){
console.log('---- sidebar navigation catch navigateToLink: ', e);
console.log('---- sidebar navigation catch clickLink: ', e);
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,23 +23,46 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { ElementFinder, ElementArrayFinder, by, protractor, browser } from 'protractor';
import { ElementFinder, ElementArrayFinder, by, browser } from 'protractor';
import { Menu } from '../menu/menu';
import { Component } from '../component';
import { Utils } from '../../utilities/utils';
export class Toolbar extends Component {
private static selectors = {
root: '.adf-toolbar',
button: 'button',
share: `.mat-icon-button[title='Share']`,
shareEdit: `.mat-icon-button[title='Shared link settings']`
shareEdit: `.mat-icon-button[title='Shared link settings']`,
view: `.mat-icon-button[title='View']`,
searchFilterToggle: `.mat-icon-button[title='Toggle search filter']`,
download: `.mat-icon-button[title='Download']`,
editFolder: 'app.toolbar.editFolder',
viewDetails: `.mat-icon-button[title='View details']`,
print: `.mat-icon-button[title='Print']`,
fullScreen: `.mat-icon-button[title='Activate full-screen mode']`,
joinLibrary: `.mat-icon-button[title='Join']`,
leaveLibrary: `.mat-icon-button[title='Leave library']`,
permanentlyDelete: `.mat-icon-button[title='Permanently delete']`,
restore: `.mat-icon-button[title='Restore']`
};
menu: Menu = new Menu();
buttons: ElementArrayFinder = this.component.all(by.css(Toolbar.selectors.button));
shareButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.share));
shareEditButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.shareEdit));
viewButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.view));
searchFiltersToggleButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.searchFilterToggle));
downloadButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.download));
editFolderButton: ElementFinder = this.component.element(by.id(Toolbar.selectors.editFolder));
viewDetailsButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.viewDetails));
printButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.print));
fullScreenButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.fullScreen));
joinButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.joinLibrary));
leaveButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.leaveLibrary));
permanentlyDeleteButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.permanentlyDelete));
restoreButton: ElementFinder = this.component.element(by.css(Toolbar.selectors.restore));
constructor(ancestor?: ElementFinder) {
super(Toolbar.selectors.root, ancestor);
@ -50,6 +73,10 @@ export class Toolbar extends Component {
return count === 0;
}
async numberOfAvailableActions() {
return await this.buttons.count();
}
async isButtonPresent(title: string) {
const elem = this.component.element(by.css(`${Toolbar.selectors.button}[title="${title}"]`));
return await elem.isPresent();
@ -75,7 +102,7 @@ export class Toolbar extends Component {
}
async closeMoreMenu() {
await browser.actions().sendKeys(protractor.Key.ESCAPE).perform();
await Utils.pressEscape();
}
async getButtonTooltip(button: ElementFinder) {
@ -87,21 +114,141 @@ export class Toolbar extends Component {
await btn.click();
}
async clickShareButton() {
async isSharedLinkSettingsPresent() {
return await browser.isElementPresent(this.shareEditButton);
}
async isSharePresent() {
return await browser.isElementPresent(this.shareButton);
}
async isViewPresent() {
return await browser.isElementPresent(this.viewButton);
}
async isToggleSearchFiltersPresent() {
return await browser.isElementPresent(this.searchFiltersToggleButton);
}
async isDownloadPresent() {
return await browser.isElementPresent(this.downloadButton);
}
async isPermanentlyDeletePresent() {
return await browser.isElementPresent(this.permanentlyDeleteButton);
}
async isRestorePresent() {
return await browser.isElementPresent(this.restoreButton);
}
async isEditFolderPresent() {
return await browser.isElementPresent(this.editFolderButton);
}
async isViewDetailsPresent() {
return await browser.isElementPresent(this.viewDetailsButton);
}
async isPrintPresent() {
return await browser.isElementPresent(this.printButton);
}
async isFullScreenPresent() {
return await browser.isElementPresent(this.fullScreenButton);
}
async clickShare() {
const btn = this.shareButton;
await btn.click();
}
async isShareButtonPresent() {
return await browser.isElementPresent(this.shareButton);
}
async clickShareEditButton() {
async clickSharedLinkSettings() {
const btn = this.shareEditButton;
await btn.click();
}
async isShareEditButtonPresent() {
return await browser.isElementPresent(this.shareEditButton);
async clickView() {
return await this.viewButton.click();
}
async clickEditFolder() {
return await this.editFolderButton.click();
}
async clickViewDetails() {
return await this.viewDetailsButton.click();
}
async clickDownload() {
return await this.downloadButton.click();
}
async clickJoin() {
return await this.joinButton.click();
}
async clickLeave() {
return await this.leaveButton.click();
}
async clickPermanentlyDelete() {
return await this.permanentlyDeleteButton.click();
}
async clickRestore() {
return await this.restoreButton.click();
}
async clickMoreActionsFavorite() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Favorite');
}
async clickMoreActionsRemoveFavorite() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Remove favorite');
}
async clickMoreActionsDelete() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Delete');
}
async clickMoreActionsManageVersions() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Manage Versions');
}
async clickMoreActionsMove() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Move');
}
async clickMoreActionsCopy() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Copy');
}
async clickMoreActionsEditOffline() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Edit offline');
}
async clickMoreActionsCancelEditing() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Cancel editing');
}
async clickMoreActionsUploadNewVersion() {
await this.openMoreMenu();
return await this.menu.clickMenuItem('Upload new version');
}
async clickFullScreen() {
return await this.fullScreenButton.click();
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -54,7 +54,11 @@ export class Viewer extends Component {
}
async waitForViewerToOpen() {
await browser.wait(EC.presenceOf(this.viewerContainer), BROWSER_WAIT_TIMEOUT);
try {
await browser.wait(EC.presenceOf(this.viewerContainer), BROWSER_WAIT_TIMEOUT);
} catch (error) {
console.log('\n-----> catch waitForViewerToOpen <-----\n', error)
}
}
async isViewerOpened() {

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -69,10 +69,15 @@ export const SIDEBAR_LABELS = {
// Page titles
export const PAGE_TITLES = {
VIEWER: 'Preview',
SEARCH: 'Search Results',
PERSONAL_FILES: 'Personal Files',
MY_LIBRARIES: 'My Libraries',
FAVORITE_LIBRARIES: 'Favorite Libraries'
FAVORITE_LIBRARIES: 'Favorite Libraries',
SHARED_FILES: 'Shared',
RECENT_FILES: 'Recent Files',
FAVORITES: 'Favorites',
TRASH: 'Trash',
VIEWER: 'Preview',
SEARCH: 'Search Results'
};
// Site visibility
@ -104,7 +109,9 @@ export const SITE_ROLES = {
export const FILES = {
docxFile: 'file-docx.docx',
docxFile2: 'file2-docx.docx',
xlsxFile: 'file-xlsx.xlsx',
xlsxFile2: 'file2-xlsx.xlsx',
pdfFile: 'file-pdf.pdf',
unsupportedFile: 'file_unsupported.3DS'
};

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -39,79 +39,95 @@ export class BrowsingPage extends Page {
await this.header.userInfo.signOut();
}
async isSnackBarPresent() {
return this.snackBar.isPresent();
}
// helper methods
async clickPersonalFilesAndWait() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.PERSONAL_FILES);
await this.dataTable.waitForHeader();
}
async clickPersonalFiles() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.PERSONAL_FILES);
await this.sidenav.clickLink(SIDEBAR_LABELS.PERSONAL_FILES);
}
async clickFileLibrariesAndWait() {
await this.sidenav.expandFileLibraries();
await this.sidenav.navigateToLink(SIDEBAR_LABELS.MY_LIBRARIES);
async clickPersonalFilesAndWait() {
await this.clickPersonalFiles();
await this.dataTable.waitForHeader();
}
async clickFileLibraries() {
await this.sidenav.expandFileLibraries();
await this.sidenav.navigateToLink(SIDEBAR_LABELS.MY_LIBRARIES);
await this.sidenav.clickLink(SIDEBAR_LABELS.FILE_LIBRARIES);
}
async goToFavoriteLibraries() {
await this.sidenav.expandFileLibraries();
await this.sidenav.navigateToLink(SIDEBAR_LABELS.FAVORITE_LIBRARIES);
async clickFileLibrariesAndWait() {
await this.clickFileLibraries();
await this.dataTable.waitForHeader();
}
async goToFavoriteLibraries() {
if ( !(await this.sidenav.isFileLibrariesMenuExpanded()) ) {
await this.sidenav.expandFileLibraries();
}
await this.sidenav.clickLink(SIDEBAR_LABELS.FAVORITE_LIBRARIES);
}
async goToFavoriteLibrariesAndWait() {
await this.goToFavoriteLibraries();
await this.dataTable.waitForHeader();
}
async goToMyLibraries() {
if ( !(await this.sidenav.isFileLibrariesMenuExpanded()) ) {
await this.sidenav.expandFileLibraries();
}
await this.sidenav.navigateToLink(SIDEBAR_LABELS.MY_LIBRARIES);
await this.sidenav.clickLink(SIDEBAR_LABELS.MY_LIBRARIES);
}
async goToMyLibrariesAndWait() {
await this.goToMyLibraries();
await this.dataTable.waitForHeader();
}
async clickRecentFiles() {
await this.sidenav.clickLink(SIDEBAR_LABELS.RECENT_FILES);
}
async clickRecentFilesAndWait() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.RECENT_FILES);
await this.clickRecentFiles();
await this.dataTable.waitForHeader();
}
async clickRecentFiles() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.RECENT_FILES);
}
async clickSharedFilesAndWait() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.SHARED_FILES);
await this.dataTable.waitForHeader();
}
async clickSharedFiles() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.SHARED_FILES);
await this.sidenav.clickLink(SIDEBAR_LABELS.SHARED_FILES);
}
async clickFavoritesAndWait() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.FAVORITES);
async clickSharedFilesAndWait() {
await this.clickSharedFiles();
await this.dataTable.waitForHeader();
}
async clickFavorites() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.FAVORITES);
await this.sidenav.clickLink(SIDEBAR_LABELS.FAVORITES);
}
async clickTrashAndWait() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.TRASH);
async clickFavoritesAndWait() {
await this.clickFavorites();
await this.dataTable.waitForHeader();
}
async clickTrash() {
await this.sidenav.navigateToLink(SIDEBAR_LABELS.TRASH);
await this.sidenav.clickLink(SIDEBAR_LABELS.TRASH);
}
async clickTrashAndWait() {
await this.clickTrash();
await this.dataTable.waitForHeader();
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -27,7 +27,7 @@ import { browser, by, ElementFinder, ExpectedConditions as EC, until } from 'pro
import { BROWSER_WAIT_TIMEOUT, USE_HASH_STRATEGY } from './../configs';
export abstract class Page {
private static locators = {
protected static locators = {
app: 'app-root',
layout: 'app-layout',
overlay: '.cdk-overlay-container',
@ -108,4 +108,10 @@ export abstract class Page {
return await this.genericErrorTitle.getText();
}
async isUndoActionPresent() {
const message = await this.snackBar.getAttribute('innerText');
return message.includes('Undo');
}
}

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,9 +23,8 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { browser, ElementFinder, by, ExpectedConditions as EC } from 'protractor';
import { browser, ElementFinder } from 'protractor';
import { BrowsingPage } from './browsing-page';
import { BROWSER_WAIT_TIMEOUT } from '../configs';
export class SearchResultsPage extends BrowsingPage {
@ -51,5 +50,8 @@ export class SearchResultsPage extends BrowsingPage {
root: ElementFinder = browser.$(SearchResultsPage.selectors.root);
waitForResults() {
return this.dataTable.waitForBody();
}
}

View File

@ -759,111 +759,118 @@
"rules": {
"visible": "app.toolbar.canViewFile"
}
}
],
"toolbarMoreMenu": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"type": "custom",
"order": 300,
"component": "app.shared-link.toggleSharedLink",
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
"id": "app.toolbar.more",
"type": "menu",
"order": 10000,
"icon": "more_vert",
"title": "APP.ACTIONS.MORE",
"children": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"type": "custom",
"order": 300,
"component": "app.shared-link.toggleSharedLink",
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
}
]
}
],
"content": [
@ -939,7 +946,7 @@
"id": "app.files.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -985,7 +992,7 @@
"id": "app.libraries.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -1014,7 +1021,7 @@
"id": "app.shared.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -1078,7 +1085,7 @@
"id": "app.recent.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -1124,7 +1131,7 @@
"id": "app.favorites.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -1179,7 +1186,7 @@
"id": "app.trashcan.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},

View File

@ -692,111 +692,118 @@
"rules": {
"visible": "app.toolbar.canViewFile"
}
}
],
"toolbarMoreMenu": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"type": "custom",
"order": 300,
"component": "app.shared-link.toggleSharedLink",
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
"id": "app.toolbar.more",
"type": "menu",
"order": 10000,
"icon": "more_vert",
"title": "APP.ACTIONS.MORE",
"children": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"type": "custom",
"order": 300,
"component": "app.shared-link.toggleSharedLink",
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
}
]
}
],
"content": [
@ -882,7 +889,7 @@
"id": "app.files.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -919,7 +926,7 @@
"id": "app.libraries.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -948,7 +955,7 @@
"id": "app.shared.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -1012,7 +1019,7 @@
"id": "app.recent.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -1058,7 +1065,7 @@
"id": "app.favorites.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},
@ -1113,7 +1120,7 @@
"id": "app.trashcan.thumbnail",
"key": "$thumbnail",
"type": "image",
"class": "image-table-cell",
"class": "adf-image-table-cell",
"sortable": false,
"desktopOnly": false
},

View File

@ -674,114 +674,121 @@
"rules": {
"visible": "app.toolbar.canViewFile"
}
}
],
"toolbarMoreMenu": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"order": 300,
"title": "APP.ACTIONS.SHARE",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
"id": "app.toolbar.more",
"type": "menu",
"order": 10000,
"icon": "more_vert",
"title": "APP.ACTIONS.MORE",
"children": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"order": 300,
"title": "APP.ACTIONS.SHARE",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
}
]
}
],
"content": [

View File

@ -710,114 +710,121 @@
"rules": {
"visible": "app.toolbar.canViewFile"
}
}
],
"toolbarMoreMenu": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"order": 300,
"title": "APP.ACTIONS.SHARE",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
"id": "app.toolbar.more",
"type": "menu",
"order": 10000,
"icon": "more_vert",
"title": "APP.ACTIONS.MORE",
"children": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"order": 300,
"title": "APP.ACTIONS.SHARE",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
}
]
}
],
"content": [

View File

@ -709,114 +709,121 @@
"rules": {
"visible": "app.toolbar.canViewFile"
}
}
],
"toolbarMoreMenu": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"order": 300,
"title": "APP.ACTIONS.SHARE",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
"id": "app.toolbar.more",
"type": "menu",
"order": 10000,
"icon": "more_vert",
"title": "APP.ACTIONS.MORE",
"children": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.viewer.share",
"order": 300,
"title": "APP.ACTIONS.SHARE",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "APP.ACTIONS.MOVE",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
}
]
}
],
"content": [

View File

@ -689,127 +689,134 @@
"rules": {
"visible": "app.toolbar.canViewFile"
}
}
],
"toolbarMoreMenu": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
"id": "app.toolbar.more",
"type": "menu",
"order": 10000,
"icon": "more_vert",
"title": "APP.ACTIONS.MORE",
"children": [
{
"id": "app.viewer.favorite.add",
"order": 100,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star_border",
"actions": {
"click": "ADD_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canAdd"
}
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
{
"id": "app.toolbar.my-secondary-action",
"order": 150,
"title": "My secondary action",
"icon": "alarm",
"actions": {
"click": "PRINT_FILE"
{
"id": "app.viewer.favorite.remove",
"order": 200,
"title": "APP.ACTIONS.FAVORITE",
"icon": "star",
"actions": {
"click": "REMOVE_FAVORITE"
},
"rules": {
"visible": "app.toolbar.favorite.canRemove"
}
},
"rules": {
"visible": "app.toolbar.canViewFile"
}
},
{
"id": "app.viewer.share",
"order": 300,
"title": "APP.ACTIONS.SHARE",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
{
"id": "app.viewer.favorite",
"comment": "workaround for Recent Files and Search API issue",
"type": "custom",
"order": 101,
"component": "app.toolbar.toggleFavorite",
"rules": {
"visible": "app.toolbar.favorite.canToggle"
}
},
"rules": {
"visible": "app.selection.file.canShare"
}
},
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
{
"id": "app.toolbar.my-secondary-action",
"order": 150,
"title": "My secondary action",
"icon": "alarm",
"actions": {
"click": "PRINT_FILE"
},
"rules": {
"visible": "app.toolbar.canViewFile"
}
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
{
"id": "app.viewer.move",
"order": 500,
"title": "My new title",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
{
"id": "app.viewer.share",
"order": 300,
"title": "APP.ACTIONS.SHARE",
"icon": "share",
"actions": {
"click": "SHARE_NODE"
},
"rules": {
"visible": "app.selection.file.canShare"
}
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
{
"id": "app.viewer.copy",
"order": 400,
"title": "APP.ACTIONS.COPY",
"icon": "content_copy",
"actions": {
"click": "COPY_NODES"
},
"rules": {
"visible": "app.toolbar.canCopyNode"
}
},
"rules": {
"visible": "app.selection.canDelete"
}
},
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
{
"id": "app.viewer.move",
"order": 500,
"title": "My new title",
"icon": "library_books",
"actions": {
"click": "MOVE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"disabled": true,
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
{
"id": "app.viewer.delete",
"order": 600,
"title": "APP.ACTIONS.DELETE",
"icon": "delete",
"actions": {
"click": "DELETE_NODES"
},
"rules": {
"visible": "app.selection.canDelete"
}
},
"rules": {
"visible": "app.toolbar.permissions"
{
"id": "app.viewer.versions",
"order": 700,
"title": "APP.ACTIONS.VERSIONS",
"icon": "history",
"actions": {
"click": "MANAGE_VERSIONS"
},
"rules": {
"visible": "app.toolbar.versions"
}
},
{
"id": "app.viewer.permissions",
"order": 800,
"title": "APP.ACTIONS.PERMISSIONS",
"disabled": true,
"icon": "settings_input_component",
"actions": {
"click": "MANAGE_PERMISSIONS"
},
"rules": {
"visible": "app.toolbar.permissions"
}
}
]
}
],
"content": [

Binary file not shown.

Binary file not shown.

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,7 +23,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { LoginPage, BrowsingPage } from '../../pages/pages';
import { LoginPage, BrowsingPage, SearchResultsPage } from '../../pages/pages';
import { SITE_VISIBILITY } from '../../configs';
import { RepoClient } from '../../utilities/repo-client/repo-client';
import { Utils } from '../../utilities/utils';
@ -31,11 +31,15 @@ import { Utils } from '../../utilities/utils';
describe('Context menu actions - multiple selection : ', () => {
const username = `user-${Utils.random()}`;
const file1 = `file1-${Utils.random()}.txt`; let file1Id;
const file2 = `file2-${Utils.random()}.txt`; let file2Id;
const parent = `parent=${Utils.random()}`; let parentId;
const folder1 = `folder1-${Utils.random()}`; let folder1Id;
const folder2 = `folder2-${Utils.random()}`; let folder2Id;
const file1 = `my-file1-${Utils.random()}.txt`; let file1Id;
const file2 = `my-file2-${Utils.random()}.txt`; let file2Id;
const fileLocked1 = `my-fileLocked1-${Utils.random()}.txt`; let fileLocked1Id;
const fileLocked2 = `my-fileLocked2-${Utils.random()}.txt`; let fileLocked2Id;
const folder1 = `my-folder1-${Utils.random()}`; let folder1Id;
const folder2 = `my-folder2-${Utils.random()}`; let folder2Id;
const fileInTrash1 = `deletedFile1-${Utils.random()}.txt`; let fileInTrash1Id;
const fileInTrash2 = `deletedFile2-${Utils.random()}.txt`; let fileInTrash2Id;
@ -43,10 +47,12 @@ describe('Context menu actions - multiple selection : ', () => {
const folderInTrash2 = `deletedFolder2-${Utils.random()}`; let folderInTrash2Id;
const siteName = `site-${Utils.random()}`;
const file1Site = `file1-${Utils.random()}.txt`;
const file2Site = `file2-${Utils.random()}.txt`;
const folder1Site = `folder1-${Utils.random()}`;
const folder2Site = `folder2-${Utils.random()}`;
const file1Site = `my-inSite-file1-${Utils.random()}.txt`;
const file2Site = `my-inSite-file2-${Utils.random()}.txt`;
const fileLocked1Site = `my-inSite-fileLocked1-${Utils.random()}.txt`; let fileLocked1SiteId;
const fileLocked2Site = `my-inSite-fileLocked2-${Utils.random()}.txt`; let fileLocked2SiteId;
const folder1Site = `my-inSite-folder1-${Utils.random()}`;
const folder2Site = `my-inSite-folder2-${Utils.random()}`;
const apis = {
admin: new RepoClient(),
@ -57,27 +63,40 @@ describe('Context menu actions - multiple selection : ', () => {
const page = new BrowsingPage();
const { dataTable } = page;
const contextMenu = dataTable.menu;
const searchResultsPage = new SearchResultsPage();
const { searchInput } = searchResultsPage.header;
beforeAll(async (done) => {
await apis.admin.people.createUser({ username });
file1Id = (await apis.user.nodes.createFile(file1)).entry.id;
file2Id = (await apis.user.nodes.createFile(file2)).entry.id;
folder1Id = (await apis.user.nodes.createFolder(folder1)).entry.id;
folder2Id = (await apis.user.nodes.createFolder(folder2)).entry.id;
parentId = (await apis.user.nodes.createFolder(parent)).entry.id;
file1Id = (await apis.user.nodes.createFile(file1, parentId)).entry.id;
file2Id = (await apis.user.nodes.createFile(file2, parentId)).entry.id;
folder1Id = (await apis.user.nodes.createFolder(folder1, parentId)).entry.id;
folder2Id = (await apis.user.nodes.createFolder(folder2, parentId)).entry.id;
fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentId)).entry.id;
fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentId)).entry.id;
await apis.user.nodes.lockFile(fileLocked1Id);
await apis.user.nodes.lockFile(fileLocked2Id);
await apis.user.sites.createSite(siteName, SITE_VISIBILITY.PUBLIC);
const docLibId = await apis.user.sites.getDocLibId(siteName);
await apis.user.nodes.createFile(file1Site, docLibId);
await apis.user.nodes.createFile(file2Site, docLibId);
await apis.user.nodes.createFolder(folder1Site, docLibId);
await apis.user.nodes.createFile(folder2Site, docLibId);
await apis.user.nodes.createFolder(folder2Site, docLibId);
fileLocked1SiteId = (await apis.user.nodes.createFile(fileLocked1Site, docLibId)).entry.id;
fileLocked2SiteId = (await apis.user.nodes.createFile(fileLocked2Site, docLibId)).entry.id;
await apis.user.nodes.lockFile(fileLocked1SiteId);
await apis.user.nodes.lockFile(fileLocked2SiteId);
await apis.user.shared.shareFilesByIds([ file1Id, file2Id ]);
await apis.user.shared.waitForApi({ expect: 2 });
await apis.user.shared.shareFilesByIds([ file1Id, file2Id, fileLocked1Id, fileLocked2Id ]);
await apis.user.shared.waitForApi({ expect: 4 });
await apis.user.favorites.addFavoritesByIds('file', [ file1Id, file2Id ]);
await apis.user.favorites.addFavoritesByIds('file', [ file1Id, file2Id, fileLocked1Id, fileLocked2Id ]);
await apis.user.favorites.addFavoritesByIds('folder', [ folder1Id, folder2Id ]);
await apis.user.favorites.waitForApi({ expect: 4 + 1 });
await apis.user.favorites.waitForApi({ expect: 6 + 1 });
fileInTrash1Id = (await apis.user.nodes.createFile(fileInTrash1)).entry.id;
fileInTrash2Id = (await apis.user.nodes.createFile(fileInTrash2)).entry.id;
@ -90,34 +109,39 @@ describe('Context menu actions - multiple selection : ', () => {
});
afterAll(async (done) => {
await apis.user.nodes.deleteNodesById([ file1Id, file2Id, folder1Id, folder2Id ]);
await apis.user.nodes.deleteNodeById(parentId);
await apis.user.sites.deleteSite(siteName);
await apis.user.trashcan.emptyTrash();
done();
});
xit('');
describe('Generic tests', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickPersonalFilesAndWait();
await dataTable.clearSelection();
await dataTable.doubleClickOnRowByName(parent);
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Context menu appears on right click on a multiple selection of items - [C286268]', async () => {
await dataTable.selectMultipleItems([ file1, file2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
});
it('Context menu appears when right clicking on a single item while having multiple items selected - [C286269]', async () => {
await dataTable.selectMultipleItems([ file2, folder1 ]);
await dataTable.rightClickOnItem(file1);
expect(await dataTable.hasContextMenu()).toBe(true, `Context menu is not displayed for ${file1}`);
expect(await dataTable.countSelectedRows()).toEqual(1, 'incorrect number of selected rows');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${file1}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`);
expect(await dataTable.hasCheckMarkIcon(file1)).toBe(true, `${file1} is not selected`);
expect(await dataTable.hasCheckMarkIcon(file2)).toBe(false, `${file2} is selected`);
expect(await dataTable.hasCheckMarkIcon(folder1)).toBe(false, `${folder1} is selected`);
@ -128,96 +152,163 @@ describe('Context menu actions - multiple selection : ', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickPersonalFilesAndWait();
await dataTable.clearSelection();
await dataTable.doubleClickOnRowByName(parent);
await dataTable.waitForBody();
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('correct actions appear when multiple files are selected - [C280661]', async () => {
await dataTable.selectMultipleItems([file1, file2]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple locked files are selected - [C297627]', async () => {
await dataTable.selectMultipleItems([fileLocked1, fileLocked2]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple folders are selected - [C280632]', async () => {
await dataTable.selectMultipleItems([folder1, folder2]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when both files and folders are selected - [C280631]', async () => {
await dataTable.selectMultipleItems([file1, file2, folder1, folder2]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
});
describe('on File Libraries', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickFileLibrariesAndWait();
await page.goToMyLibrariesAndWait();
await dataTable.doubleClickOnRowByName(siteName);
await dataTable.waitForHeader();
await dataTable.clearSelection();
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('correct actions appear when multiple files are selected - [C280641]', async () => {
await dataTable.selectMultipleItems([ file1Site, file2Site ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple locked files are selected - [C297628]', async () => {
await dataTable.selectMultipleItems([ fileLocked1Site, fileLocked2Site ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple folders are selected - [C280574]', async () => {
await dataTable.selectMultipleItems([ folder1Site, folder2Site ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when both files and folders are selected - [C280642]', async () => {
await dataTable.selectMultipleItems([ file1Site, file2Site, folder1Site, folder2Site ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
});
@ -229,17 +320,43 @@ describe('Context menu actions - multiple selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('correct actions appear when multiple files are selected - [C280648]', async () => {
await dataTable.selectMultipleItems([ file1, file2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is not displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple locked files are selected - [C297629]', async () => {
await dataTable.selectMultipleItems([ fileLocked1, fileLocked2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is not displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
});
@ -251,17 +368,43 @@ describe('Context menu actions - multiple selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('correct actions appear when multiple files are selected - [C280652]', async () => {
await dataTable.selectMultipleItems([ file1, file2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple locked files are selected - [C297630]', async () => {
await dataTable.selectMultipleItems([ fileLocked1, fileLocked2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
});
@ -273,46 +416,77 @@ describe('Context menu actions - multiple selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('correct actions appear when multiple files are selected - [C280656]', async () => {
await dataTable.selectMultipleItems([ file1, file2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
// TODO: enable when ACA-1794 is fixed
// expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple locked files are selected - [C297631]', async () => {
await dataTable.selectMultipleItems([ fileLocked1, fileLocked2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple folders are selected - [C280664]', async () => {
await dataTable.selectMultipleItems([ folder1, folder2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
// TODO: enable when ACA-1794 is fixed
// expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when both files and folders are selected - [C280657]', async () => {
await dataTable.selectMultipleItems([ file1, file2, folder1, folder2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, 'Download is not displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`);
// TODO: enable when ACA-1794 is fixed
// expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
});
@ -324,46 +498,159 @@ describe('Context menu actions - multiple selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('correct actions appear when multiple files are selected - [C286273]', async () => {
await dataTable.selectMultipleItems([ fileInTrash1, fileInTrash2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('Permanently delete')).toBe(true, 'Permanently delete is not displayed');
expect(await contextMenu.isMenuItemPresent('Restore')).toBe(true, 'Restore is not displayed');
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(false, 'Download is displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(false, `Copy is displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(false, `Favorite is displayed`);
expect(await contextMenu.isPermanentDeletePresent()).toBe(true, 'Permanently delete is not displayed');
expect(await contextMenu.isRestorePresent()).toBe(true, 'Restore is not displayed');
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(false, 'Download is displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(false, `Copy is displayed`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`);
expect(await contextMenu.isFavoritePresent()).toBe(false, `Favorite is displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple folders are selected - [C286274]', async () => {
await dataTable.selectMultipleItems([ folderInTrash1, folderInTrash2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('Permanently delete')).toBe(true, 'Permanently delete is not displayed');
expect(await contextMenu.isMenuItemPresent('Restore')).toBe(true, 'Restore is not displayed');
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(false, 'Download is displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(false, `Copy is displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(false, `Favorite is displayed`);
expect(await contextMenu.isPermanentDeletePresent()).toBe(true, 'Permanently delete is not displayed');
expect(await contextMenu.isRestorePresent()).toBe(true, 'Restore is not displayed');
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(false, 'Download is displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(false, `Copy is displayed`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`);
expect(await contextMenu.isFavoritePresent()).toBe(false, `Favorite is displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when both files and folders are selected - [C286275]', async () => {
await dataTable.selectMultipleItems([ fileInTrash1, fileInTrash2, folderInTrash1, folderInTrash2 ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isMenuItemPresent('Permanently delete')).toBe(true, 'Permanently delete is not displayed');
expect(await contextMenu.isMenuItemPresent('Restore')).toBe(true, 'Restore is not displayed');
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, 'View is displayed');
expect(await contextMenu.isMenuItemPresent('Download')).toBe(false, 'Download is displayed');
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, 'Edit is displayed');
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(false, `Copy is displayed`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(false, `Favorite is displayed`);
expect(await contextMenu.isPermanentDeletePresent()).toBe(true, 'Permanently delete is not displayed');
expect(await contextMenu.isRestorePresent()).toBe(true, 'Restore is not displayed');
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(false, 'Download is displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(false, `Copy is displayed`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`);
expect(await contextMenu.isFavoritePresent()).toBe(false, `Favorite is displayed`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
});
describe('on Search Results', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickPersonalFilesAndWait();
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('correct actions appear when multiple files are selected - [C291831]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkOnlyFiles();
await searchInput.searchForTextAndCloseSearchOptions('my-inSite-file');
await dataTable.selectMultipleItems([ file1Site, file2Site ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`);
expect(await contextMenu.isToggleFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple locked files are selected - [C297632]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkOnlyFiles();
await searchInput.searchForTextAndCloseSearchOptions('my-inSite-file');
await dataTable.selectMultipleItems([ fileLocked1Site, fileLocked2Site ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`);
expect(await contextMenu.isToggleFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when multiple folders are selected - [C291832]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkOnlyFolders();
await searchInput.searchForTextAndCloseSearchOptions('my-inSite-folder');
await dataTable.selectMultipleItems([ folder1Site, folder2Site ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`);
expect(await contextMenu.isToggleFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
it('correct actions appear when both files and folders are selected - [C291833]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkFilesAndFolders();
await searchInput.searchForTextAndCloseSearchOptions('my-inSite-f');
await dataTable.selectMultipleItems([ file1Site, file2Site, folder1Site, folder2Site ]);
await dataTable.rightClickOnMultipleSelection();
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`);
expect(await contextMenu.isViewPresent()).toBe(false, 'View is displayed');
expect(await contextMenu.isDownloadPresent()).toBe(true, 'Download is not displayed');
expect(await contextMenu.isEditFolderPresent()).toBe(false, 'Edit folder is displayed');
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`);
expect(await contextMenu.isToggleFavoritePresent()).toBe(true, `Toggle favorite is not displayed`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`);
});
});
});

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -23,7 +23,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { LoginPage, BrowsingPage } from '../../pages/pages';
import { LoginPage, BrowsingPage, SearchResultsPage } from '../../pages/pages';
import { SITE_VISIBILITY } from '../../configs';
import { RepoClient } from '../../utilities/repo-client/repo-client';
import { Utils } from '../../utilities/utils';
@ -35,9 +35,11 @@ describe('Context menu actions - single selection : ', () => {
const folderUser = `folderUser-${Utils.random()}`; let folderUserId;
const fileInTrash = `fileForDelete-${Utils.random()}.txt`; let fileInTrashId;
const folderInTrash = `folderForDelete-${Utils.random()}`; let folderInTrashId;
const fileLocked = `fileLocked-${Utils.random()}.txt`; let fileLockedId;
const siteName = `userSite-${Utils.random()}`;
const fileSiteUser = `fileUser-${Utils.random()}.txt`;
const fileLockedInSite = `file-locked-site-${Utils.random()}.txt`; let fileLockedInSiteId;
const folderSiteUser = `folderUser-${Utils.random()}`;
const adminPublic = `admin-public-${Utils.random()}`;
@ -52,6 +54,8 @@ describe('Context menu actions - single selection : ', () => {
const page = new BrowsingPage();
const { dataTable } = page;
const contextMenu = dataTable.menu;
const searchResultsPage = new SearchResultsPage();
const { searchInput } = searchResultsPage.header;
beforeAll(async (done) => {
await apis.admin.people.createUser({ username });
@ -59,10 +63,15 @@ describe('Context menu actions - single selection : ', () => {
fileUserId = (await apis.user.nodes.createFile(fileUser)).entry.id;
folderUserId = (await apis.user.nodes.createFolder(folderUser)).entry.id;
fileLockedId = (await apis.user.nodes.createFile(fileLocked)).entry.id;
await apis.user.nodes.lockFile(fileLockedId);
await apis.user.sites.createSite(siteName, SITE_VISIBILITY.PUBLIC);
const docLibId = await apis.user.sites.getDocLibId(siteName);
await apis.user.nodes.createFile(fileSiteUser, docLibId);
fileLockedInSiteId = (await apis.user.nodes.createFile(fileLockedInSite, docLibId)).entry.id;
await apis.user.nodes.createFolder(folderSiteUser, docLibId);
await apis.user.nodes.lockFile(fileLockedInSiteId);
fileInTrashId = (await apis.user.nodes.createFiles([fileInTrash])).entry.id;
folderInTrashId = (await apis.user.nodes.createFolders([ folderInTrash ])).entry.id;
@ -70,11 +79,13 @@ describe('Context menu actions - single selection : ', () => {
await apis.user.nodes.deleteNodeById(folderInTrashId, false);
await apis.user.shared.shareFileById(fileUserId);
await apis.user.shared.waitForApi({ expect: 1 });
await apis.user.shared.shareFileById(fileLockedId);
await apis.user.shared.waitForApi({ expect: 2 });
await apis.user.favorites.addFavoriteById('file', fileUserId);
await apis.user.favorites.addFavoriteById('file', fileLockedId);
await apis.user.favorites.addFavoriteById('folder', folderUserId);
await apis.user.favorites.waitForApi({ expect: 3 });
await apis.user.favorites.waitForApi({ expect: 4 });
await apis.admin.sites.createSite(adminPublic);
await apis.admin.sites.createSite(adminModerated, SITE_VISIBILITY.MODERATED);
@ -82,6 +93,10 @@ describe('Context menu actions - single selection : ', () => {
await apis.user.favorites.addFavoriteById('site', adminModerated);
await apis.user.sites.requestToJoin(adminModerated);
await apis.user.queries.waitForSites(siteName, { expect: 1 });
await apis.user.queries.waitForSites(adminPublic, { expect: 1 });
await apis.user.queries.waitForSites(adminModerated, { expect: 1 });
await loginPage.loginWith(username);
done();
});
@ -96,8 +111,6 @@ describe('Context menu actions - single selection : ', () => {
done();
});
xit('');
describe('Generic tests', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
@ -105,35 +118,47 @@ describe('Context menu actions - single selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Row is marked with a check circle icon on direct right click - [C286252]', async () => {
await dataTable.rightClickOnItem(fileUser);
expect(await dataTable.hasCheckMarkIcon(fileUser)).toBe(true, 'check mark missing');
});
it('Context menu appears on direct right click on an item - [C286253]', async () => {
await dataTable.rightClickOnItem(fileUser);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
});
it('Context menu appears when selecting an item and then right clicking on it - [C286254]', async () => {
await dataTable.selectItem(fileUser);
await dataTable.rightClickOnItem(fileUser);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
});
it('Context menu appears correctly when right clicking on another item - [C284666]', async () => {
await dataTable.selectItem(fileUser);
await dataTable.rightClickOnItem(folderUser);
expect(await dataTable.hasContextMenu()).toBe(true, `Context menu is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(true, `Edit is not displayed for ${folderUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderUser}`);
expect(await dataTable.hasCheckMarkIcon(folderUser)).toBe(true, `${folderUser} is not selected`);
expect(await dataTable.hasCheckMarkIcon(fileUser)).toBe(false, `${fileUser} is not selected`);
});
it('Context menu closes when clicking away from it - [C280619]', async () => {
await dataTable.rightClickOnItem(fileUser);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
await page.sidenav.getActiveLink().click();
expect(await dataTable.hasContextMenu()).toBe(false, 'Context menu is displayed');
});
});
@ -146,72 +171,136 @@ describe('Context menu actions - single selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Context menu has the correct actions for a file - [C280615]', async () => {
await dataTable.rightClickOnItem(fileUser);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(true, `View is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${fileUser}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${fileUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`);
expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${fileUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileUser}`);
});
it('Context menu has the correct actions for a locked file - [C297633]', async () => {
await dataTable.rightClickOnItem(fileLocked);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`);
expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLocked}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${fileLocked}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLocked}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`);
});
it('Context menu has the correct actions for a folder - [C280616]', async () => {
await dataTable.rightClickOnItem(folderUser);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not enabled for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(true, `Edit is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, `View is displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(false, `Manage Versions is displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(false, `Share is displayed for ${folderUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${folderUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderUser}`);
expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folderUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folderUser}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${folderUser}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${folderUser}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${folderUser}`);
expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folderUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`);
expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderUser}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderUser}`);
});
});
describe('on File Libraries', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickFileLibrariesAndWait();
await page.goToMyLibrariesAndWait();
await dataTable.doubleClickOnRowByName(siteName);
await dataTable.waitForHeader();
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Context menu has the correct actions for a file - [C280594]', async () => {
await dataTable.rightClickOnItem(fileSiteUser);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(true, `View is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${fileSiteUser}`);
expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${fileSiteUser}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileSiteUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileSiteUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileSiteUser}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileSiteUser}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileSiteUser}`);
});
it('Context menu has the correct actions for a locked file - [C297634]', async () => {
await dataTable.rightClickOnItem(fileLockedInSite);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(true, `Cancel editing is displayed for ${fileLockedInSite}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLockedInSite}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLockedInSite}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLockedInSite}`);
});
it('Context menu has the correct actions for a folder - [C280595]', async () => {
await dataTable.rightClickOnItem(folderSiteUser);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not enabled for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(true, `Edit is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, `View is displayed for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(false, `Manage Versions displayed for ${folderSiteUser}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(false, `Share is displayed for ${folderSiteUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderSiteUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions displayed for ${folderSiteUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version displayed for ${folderSiteUser}`);
expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderSiteUser}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderSiteUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderSiteUser}`);
});
});
@ -222,40 +311,85 @@ describe('Context menu actions - single selection : ', () => {
done();
});
it('Available actions when a library is selected - My Libraries - [C290080]', async () => {
await page.goToMyLibraries();
await dataTable.rightClickOnItem(siteName);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
expect(await contextMenu.isMenuItemPresent('Leave library')).toBe(true, `Leave is not displayed for ${siteName}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${siteName}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${siteName}`);
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Available actions when a library is selected - Favorite Libraries - user is a member - [C290081]', async () => {
await page.goToFavoriteLibraries();
it('Available actions for a library - My Libraries - [C290080]', async () => {
await page.goToMyLibrariesAndWait();
await dataTable.rightClickOnItem(siteName);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
expect(await contextMenu.isMenuItemPresent('Leave library')).toBe(true, `Leave is not displayed for ${siteName}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${siteName}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${siteName}`);
expect(await contextMenu.isLeaveLibraryPresent()).toBe(true, `Leave is not displayed for ${siteName}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${siteName}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${siteName}`);
});
it('Available actions when a library is selected - Favorite Libraries - user is not a member - [C290082]', async () => {
await page.goToFavoriteLibraries();
it('Available actions for a library - Favorite Libraries - user is a member - [C290081]', async () => {
await page.goToFavoriteLibrariesAndWait();
await dataTable.rightClickOnItem(siteName);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
expect(await contextMenu.isLeaveLibraryPresent()).toBe(true, `Leave is not displayed for ${siteName}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${siteName}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${siteName}`);
});
it('Available actions for a library - Favorite Libraries - user is not a member - [C290082]', async () => {
await page.goToFavoriteLibrariesAndWait();
await dataTable.rightClickOnItem(adminPublic);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
expect(await contextMenu.isMenuItemPresent('Join')).toBe(true, `Join is not displayed for ${adminPublic}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${adminPublic}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${adminPublic}`);
expect(await contextMenu.isJoinLibraryPresent()).toBe(true, `Join is not displayed for ${adminPublic}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${adminPublic}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${adminPublic}`);
});
it('Available actions when a library is selected - Favorite Libraries - user requested to join - [C290089]', async () => {
await page.goToFavoriteLibraries();
it('Available actions for a moderated library - Favorite Libraries - user requested to join - [C290089]', async () => {
await page.goToFavoriteLibrariesAndWait();
await dataTable.rightClickOnItem(adminModerated);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
expect(await contextMenu.isMenuItemPresent('Cancel join')).toBe(true, `Cancel join is not displayed for ${adminModerated}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${adminModerated}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${adminModerated}`);
expect(await contextMenu.isCancelJoinPresent()).toBe(true, `Cancel join is not displayed for ${adminModerated}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${adminModerated}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${adminModerated}`);
});
it('Available actions for a library - Search Results - user is a member - [C291812]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkLibraries();
await searchInput.searchForTextAndCloseSearchOptions(siteName);
await dataTable.rightClickOnItem(siteName);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
expect(await contextMenu.isLeaveLibraryPresent()).toBe(true, `Leave is not displayed for ${siteName}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${siteName}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${siteName}`);
});
it('Available actions for a library - Search Results - user is not a member - [C291813]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkLibraries();
await searchInput.searchForTextAndCloseSearchOptions(adminPublic);
await dataTable.rightClickOnItem(adminPublic);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
expect(await contextMenu.isJoinLibraryPresent()).toBe(true, `Join is not displayed for ${adminPublic}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${adminPublic}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${adminPublic}`);
});
it('Available actions for a moderated library - Search Results - user requested to join - [C291814]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkLibraries();
await searchInput.searchForTextAndCloseSearchOptions(adminModerated);
await dataTable.rightClickOnItem(adminModerated);
expect(await dataTable.hasContextMenu()).toBe(true, 'Context menu is not displayed');
expect(await contextMenu.isCancelJoinPresent()).toBe(true, `Cancel join is not displayed for ${adminModerated}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${adminModerated}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${adminModerated}`);
});
});
@ -266,19 +400,49 @@ describe('Context menu actions - single selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Context menu has the correct actions for a file - [C280601]', async () => {
await dataTable.rightClickOnItem(fileUser);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(true, `View is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Shared link settings')).toBe(true, `Shared link settings is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${fileUser}`);
// TODO: change expect to true when ACA-2173 is done
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${fileUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed for ${fileUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileUser}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileUser}`);
});
it('Context menu has the correct actions for a locked file - [C297635]', async () => {
await dataTable.rightClickOnItem(fileLocked);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`);
// TODO: change expect to true when ACA-2173 is done
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileLocked}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${fileLocked}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`);
expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed for ${fileLocked}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileLocked}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileLocked}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLocked}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`);
});
});
@ -289,19 +453,47 @@ describe('Context menu actions - single selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Context menu has the correct actions for a file - [C280622]', async () => {
await dataTable.rightClickOnItem(fileUser);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(true, `View is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${fileUser}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${fileUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${fileUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileUser}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileUser}`);
});
it('Context menu has the correct actions for a locked file - [C297636]', async () => {
await dataTable.rightClickOnItem(fileLocked);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${fileLocked}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLocked}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileLocked}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileLocked}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLocked}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`);
});
});
@ -312,35 +504,64 @@ describe('Context menu actions - single selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Context menu has the correct actions for a file - [C280608]', async () => {
await dataTable.rightClickOnItem(fileUser);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(true, `View is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions is not displayed for ${fileUser}`);
// TODO: enable when ACA-1794 is fixed
// expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`);
expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${fileUser}`);
// TODO: change expect to true when ACA-2174 is done
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${fileUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${fileUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileUser}`);
});
it('Context menu has the correct actions for a locked file - [C297637]', async () => {
await dataTable.rightClickOnItem(fileLocked);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`);
// TODO: change expect to true when ACA-2174 is done
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileLocked}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${fileLocked}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLocked}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${fileLocked}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`);
});
it('Context menu has the correct actions for a folder - [C280609]', async () => {
await dataTable.rightClickOnItem(folderUser);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not enabled for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(true, `Edit is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderUser}`);
// TODO: enable when ACA-1794 is fixed
// expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, `View is displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(false, `Manage Versions is displayed for ${folderUser}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(false, `Share is displayed for ${folderUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${folderUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderUser}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${folderUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folderUser}`);
expect(await contextMenu.isMovePresent()).toBe(true, `Move is not displayed for ${folderUser}`);
expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is not displayed for ${folderUser}`);
expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folderUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`);
expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderUser}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderUser}`);
});
});
@ -351,40 +572,126 @@ describe('Context menu actions - single selection : ', () => {
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Context menu has the correct actions for a file - [C286258]', async () => {
await dataTable.rightClickOnItem(fileInTrash);
expect(await contextMenu.isMenuItemPresent('Permanently delete'))
.toBe(true, `Permanently delete is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Restore')).toBe(true, `Restore is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(false, `Download is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, `View is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(false, `Favorite is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(false, `Copy is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(false, `Share is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions'))
.toBe(false, `Manage Versions is not displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${fileInTrash}`);
expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${fileInTrash}`);
expect(await contextMenu.isPermanentDeletePresent()).toBe(true, `Permanently delete is not displayed for ${fileInTrash}`);
expect(await contextMenu.isRestorePresent()).toBe(true, `Restore is not displayed for ${fileInTrash}`);
expect(await contextMenu.isDownloadPresent()).toBe(false, `Download is displayed for ${fileInTrash}`);
expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${fileInTrash}`);
expect(await contextMenu.isFavoritePresent()).toBe(false, `Favorite is displayed for ${fileInTrash}`);
expect(await contextMenu.isCopyPresent()).toBe(false, `Copy is displayed for ${fileInTrash}`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${fileInTrash}`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileInTrash}`);
expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${fileInTrash}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${fileInTrash}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${fileInTrash}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileInTrash}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileInTrash}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileInTrash}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileInTrash}`);
});
it('Context menu has the correct actions for a folder - [C286259]', async () => {
await dataTable.rightClickOnItem(folderInTrash);
expect(await contextMenu.isMenuItemPresent('Permanently delete'))
.toBe(true, `Permanently delete is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Restore')).toBe(true, `Restore is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Download')).toBe(false, `Download is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('View')).toBe(false, `View is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(false, `Favorite is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Copy')).toBe(false, `Copy is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Share')).toBe(false, `Share is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Manage Versions'))
.toBe(false, `Manage Versions is not displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${folderInTrash}`);
expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${folderInTrash}`);
expect(await contextMenu.isPermanentDeletePresent()).toBe(true, `Permanently delete is not displayed for ${folderInTrash}`);
expect(await contextMenu.isRestorePresent()).toBe(true, `Restore is not displayed for ${folderInTrash}`);
expect(await contextMenu.isDownloadPresent()).toBe(false, `Download is displayed for ${folderInTrash}`);
expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderInTrash}`);
expect(await contextMenu.isFavoritePresent()).toBe(false, `Favorite is displayed for ${folderInTrash}`);
expect(await contextMenu.isCopyPresent()).toBe(false, `Copy is displayed for ${folderInTrash}`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${folderInTrash}`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${folderInTrash}`);
expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderInTrash}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folderInTrash}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderInTrash}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${folderInTrash}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${folderInTrash}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderInTrash}`);
});
});
describe('on Search Results', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickPersonalFilesAndWait();
done();
});
afterAll(async (done) => {
await Utils.pressEscape();
done();
});
it('Context menu has the correct actions for a file - [C291827]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkOnlyFiles();
await searchInput.searchForTextAndCloseSearchOptions(fileSiteUser);
await dataTable.rightClickOnItem(fileSiteUser);
expect(await contextMenu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileSiteUser}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isToggleFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${fileSiteUser}`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileSiteUser}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileSiteUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileSiteUser}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileSiteUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileSiteUser}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileSiteUser}`);
});
it('Context menu has the correct actions for a locked file - [C297638]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkOnlyFiles();
await searchInput.searchForTextAndCloseSearchOptions(fileLocked);
await dataTable.rightClickOnItem(fileLocked);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`);
expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`);
expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${fileLocked}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileLocked}`);
expect(await contextMenu.isSharePresent()).toBe(true, `Share is not displayed for ${fileLocked}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions not displayed for ${fileLocked}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version not displayed for ${fileLocked}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${fileLocked}`);
expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`);
expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${fileLocked}`);
});
it('Context menu has the correct actions for a folder - [C291828]', async () => {
await searchInput.clickSearchButton();
await searchInput.checkOnlyFolders();
await searchInput.searchForTextAndCloseSearchOptions(folderSiteUser);
await dataTable.rightClickOnItem(folderSiteUser);
expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isToggleFavoritePresent()).toBe(true, `Toggle favorite is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${folderSiteUser}`);
expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${folderSiteUser}`);
expect(await contextMenu.isManagePermissionsPresent()).toBe(true, `Permissions is not displayed for ${folderSiteUser}`);
expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folderSiteUser}`);
expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions displayed for ${folderSiteUser}`);
expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version displayed for ${folderSiteUser}`);
expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folderSiteUser}`);
expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderSiteUser}`);
expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderSiteUser}`);
});
});
});

556
e2e/suites/actions/copy.test.ts Executable file
View File

@ -0,0 +1,556 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2019 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 { LoginPage, BrowsingPage } from '../../pages/pages';
import { CopyMoveDialog } from './../../components/dialog/copy-move-dialog';
import { RepoClient } from '../../utilities/repo-client/repo-client';
import { Utils } from '../../utilities/utils';
describe('Copy content', () => {
const username = `user-${Utils.random()}`;
const source = `source-${Utils.random()}`; let sourceId;
const destinationPF = `destinationPersonal-${Utils.random()}`; let destinationIdPF;
const destinationRF = `destinationRecent-${Utils.random()}`; let destinationIdRF;
const destinationSF = `destinationShared-${Utils.random()}`; let destinationIdSF;
const destinationFav = `destinationFav-${Utils.random()}`; let destinationIdFav;
const file1 = `file1-${Utils.random()}.txt`; let file1Id;
const folder1 = `folder1-${Utils.random()}`; let folder1Id;
const fileInFolder = `fileInFolder-${Utils.random()}.txt`;
const file2 = `file2-${Utils.random()}.txt`; let file2Id;
const file3 = `file3-${Utils.random()}.txt`; let file3Id;
const existingFile = `existing-${Utils.random()}`; let existingFileId;
const existingFolder = `existing-${Utils.random()}`;
let existingId1, existingId2, existingId2RF, existingId2SF, existingId2Fav;
const file2InFolder = `file2InFolder-${Utils.random()}.txt`;
const file3InFolder = `file3InFolder-${Utils.random()}.txt`;
const siteName = `site-${Utils.random()}`;
const folderSitePF = `folderSitePersonal-${Utils.random()}`;
const folderSiteRF = `folderSiteRecent-${Utils.random()}`;
const folderSiteSF = `folderSiteShared-${Utils.random()}`;
const folderSiteFav = `folderSiteFav-${Utils.random()}`;
const apis = {
admin: new RepoClient(),
user: new RepoClient(username, username)
};
const loginPage = new LoginPage();
const page = new BrowsingPage();
const { dataTable, toolbar } = page;
const copyDialog = new CopyMoveDialog();
beforeAll(async (done) => {
await apis.admin.people.createUser({ username });
sourceId = (await apis.user.nodes.createFolder(source)).entry.id;
destinationIdPF = (await apis.user.nodes.createFolder(destinationPF)).entry.id;
destinationIdRF = (await apis.user.nodes.createFolder(destinationRF)).entry.id;
destinationIdSF = (await apis.user.nodes.createFolder(destinationSF)).entry.id;
destinationIdFav = (await apis.user.nodes.createFolder(destinationFav)).entry.id;
file1Id = (await apis.user.nodes.createFile(file1, sourceId)).entry.id;
await apis.user.shared.shareFileById(file1Id);
await apis.user.favorites.addFavoriteById('file', file1Id);
folder1Id = (await apis.user.nodes.createFolder(folder1, sourceId)).entry.id;
await apis.user.nodes.createFile(fileInFolder, folder1Id);
await apis.user.favorites.addFavoriteById('folder', folder1Id);
file2Id = (await apis.user.nodes.createFile(file2, sourceId)).entry.id;
file3Id = (await apis.user.nodes.createFile(file3, sourceId)).entry.id;
await apis.user.shared.shareFileById(file2Id);
await apis.user.shared.shareFileById(file3Id);
await apis.user.favorites.addFavoriteById('file', file2Id);
await apis.user.favorites.addFavoriteById('file', file3Id);
existingFileId = (await apis.user.nodes.createFile(`${existingFile}.txt`, sourceId)).entry.id;
await apis.user.shared.shareFileById(existingFileId);
await apis.user.favorites.addFavoriteById('file', existingFileId);
await apis.user.nodes.createFile(`${existingFile}.txt`, destinationIdPF);
await apis.user.nodes.createFile(`${existingFile}.txt`, destinationIdRF);
await apis.user.nodes.createFile(`${existingFile}.txt`, destinationIdSF);
await apis.user.nodes.createFile(`${existingFile}.txt`, destinationIdFav);
existingId1 = (await apis.user.nodes.createFolder(existingFolder, sourceId)).entry.id;
existingId2 = (await apis.user.nodes.createFolder(existingFolder, destinationIdPF)).entry.id;
existingId2RF = (await apis.user.nodes.createFolder(existingFolder, destinationIdRF)).entry.id;
existingId2SF = (await apis.user.nodes.createFolder(existingFolder, destinationIdSF)).entry.id;
existingId2Fav = (await apis.user.nodes.createFolder(existingFolder, destinationIdFav)).entry.id;
await apis.user.nodes.createFile(file2InFolder, existingId1);
await apis.user.nodes.createFile(file3InFolder, existingId2);
await apis.user.nodes.createFile(file3InFolder, existingId2RF);
await apis.user.nodes.createFile(file3InFolder, existingId2SF);
await apis.user.nodes.createFile(file3InFolder, existingId2Fav);
await apis.user.favorites.addFavoriteById('folder', existingId1);
await apis.user.sites.createSite(siteName);
const docLibId = await apis.user.sites.getDocLibId(siteName);
await apis.user.nodes.createFolder(folderSitePF, docLibId);
await apis.user.nodes.createFolder(folderSiteRF, docLibId);
await apis.user.nodes.createFolder(folderSiteSF, docLibId);
await apis.user.nodes.createFolder(folderSiteFav, docLibId);
await apis.user.shared.waitForApi({ expect: 4 });
await apis.user.favorites.waitForApi({ expect: 7 });
await loginPage.loginWith(username);
done();
});
afterAll(async (done) => {
await apis.user.nodes.deleteNodeById(sourceId);
await apis.user.nodes.deleteNodeById(destinationIdPF);
await apis.user.nodes.deleteNodeById(destinationIdRF);
await apis.user.nodes.deleteNodeById(destinationIdSF);
await apis.user.nodes.deleteNodeById(destinationIdFav);
await apis.user.sites.deleteSite(siteName);
done();
});
describe('from Personal Files', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(source);
done();
});
it('Copy a file - [C217135]', async () => {
await dataTable.selectItem(file1);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationPF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationPF);
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`);
});
it('Copy a folder with content - [C291888]', async () => {
await dataTable.selectItem(folder1);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationPF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(folder1)).toBe(true, `${folder1} not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationPF);
expect(await dataTable.isItemPresent(folder1)).toBe(true, `${folder1} not present in destination folder`);
expect(await dataTable.isItemPresent(fileInFolder)).toBe(false, `${fileInFolder} is present in destination`);
await dataTable.doubleClickOnRowByName(folder1);
expect(await dataTable.isItemPresent(fileInFolder)).toBe(true, `${fileInFolder} is not present in parent folder`);
});
it('Copy multiple items - [C291889]', async () => {
await dataTable.selectMultipleItems([file2, file3]);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationPF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 2 items');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(file2)).toBe(true, `${file2} not present in source folder`);
expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationPF);
expect(await dataTable.isItemPresent(file2)).toBe(true, `${file2} not present in destination folder`);
expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} not present in destination folder`);
});
it('Copy a file with a name that already exists on the destination - [C217137]', async () => {
await dataTable.selectItem(existingFile);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationPF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(`${existingFile}.txt`)).toBe(true, `${existingFile}.txt not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationPF);
expect(await dataTable.isItemPresent(`${existingFile}.txt`)).toBe(true, `${existingFile}.txt not present in destination folder`);
expect(await dataTable.isItemPresent(`${existingFile}-1.txt`)).toBe(true, `${existingFile}-1.txt not present in destination folder`);
});
it('Copy a folder with a name that already exists on the destination - [C217138]', async () => {
await dataTable.selectItem(existingFolder);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationPF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(existingFolder)).toBe(true, `${existingFolder} not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationPF);
expect(await dataTable.isItemPresent(existingFolder)).toBe(true, `${existingFolder} not present in destination folder`);
await dataTable.doubleClickOnRowByName(existingFolder);
expect(await dataTable.isItemPresent(file2InFolder)).toBe(true, `${file2InFolder} not present in destination folder`);
expect(await dataTable.isItemPresent(file3InFolder)).toBe(true, `${file3InFolder} not present in destination folder`);
});
it('Copy items into a library - [C280282]', async () => {
await dataTable.selectMultipleItems([file1, folder1]);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('File Libraries');
await copyDialog.doubleClickOnRow(siteName);
await copyDialog.doubleClickOnRow('documentLibrary');
await copyDialog.selectDestination(folderSitePF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 2 items');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in source folder`);
expect(await dataTable.isItemPresent(folder1)).toBe(true, `${folder1} not present in source folder`);
await page.goToMyLibraries();
await dataTable.doubleClickOnRowByName(siteName);
await dataTable.doubleClickOnRowByName(folderSitePF);
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`);
expect(await dataTable.isItemPresent(folder1)).toBe(true, `${folder1} not present in destination folder`);
await dataTable.doubleClickOnRowByName(folder1);
expect(await dataTable.isItemPresent(fileInFolder)).toBe(true, `${fileInFolder} not present in parent folder`);
});
});
describe('from Recent Files', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickRecentFilesAndWait();
done();
});
it('Copy a file - [C280194]', async () => {
await dataTable.selectItem(file1, source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationRF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationRF);
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`);
});
it('Copy multiple items - [C280201]', async () => {
await dataTable.selectMultipleItems([file2, file3], source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationRF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 2 items');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationRF);
expect(await dataTable.isItemPresent(file2)).toBe(true, `${file2} not present in destination folder`);
expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} not present in destination folder`);
});
it('Copy a file with a name that already exists on the destination - [C280196]', async () => {
await dataTable.selectItem(existingFile, source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationRF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationRF);
expect(await dataTable.isItemPresent(`${existingFile}.txt`)).toBe(true, `${existingFile}.txt not present in destination folder`);
expect(await dataTable.isItemPresent(`${existingFile}-1.txt`)).toBe(true, `${existingFile}-1.txt not present in destination folder`);
});
it('Copy items into a library - [C291899]', async () => {
await dataTable.selectItem(file1, source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('File Libraries');
await copyDialog.doubleClickOnRow(siteName);
await copyDialog.doubleClickOnRow('documentLibrary');
await copyDialog.selectDestination(folderSiteRF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
await page.goToMyLibraries();
await dataTable.doubleClickOnRowByName(siteName);
await dataTable.doubleClickOnRowByName(folderSiteRF);
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`);
});
});
describe('from Shared Files', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickSharedFilesAndWait();
done();
});
it('Copy a file - [C280206]', async () => {
await dataTable.selectItem(file1, source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationSF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationSF);
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`);
});
it('Copy multiple items - [C280213]', async () => {
await dataTable.selectMultipleItems([file2, file3], source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationSF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 2 items');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationSF);
expect(await dataTable.isItemPresent(file2)).toBe(true, `${file2} not present in destination folder`);
expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} not present in destination folder`);
});
it('Copy a file with a name that already exists on the destination - [C280208]', async () => {
await dataTable.selectItem(existingFile, source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationSF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationSF);
expect(await dataTable.isItemPresent(`${existingFile}.txt`)).toBe(true, `${existingFile}.txt not present in destination folder`);
expect(await dataTable.isItemPresent(`${existingFile}-1.txt`)).toBe(true, `${existingFile}-1.txt not present in destination folder`);
});
it('Copy items into a library - [C291900]', async () => {
await dataTable.selectItem(file1, source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('File Libraries');
await copyDialog.doubleClickOnRow(siteName);
await copyDialog.doubleClickOnRow('documentLibrary');
await copyDialog.selectDestination(folderSiteSF);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in source folder`);
await page.goToMyLibraries();
await dataTable.doubleClickOnRowByName(siteName);
await dataTable.doubleClickOnRowByName(folderSiteSF);
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`);
});
});
describe('from Favorites', () => {
beforeEach(async (done) => {
await Utils.pressEscape();
await page.clickFavoritesAndWait();
done();
});
it('Copy a file - [C280218]', async () => {
await dataTable.selectItem(file1);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationFav);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationFav);
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`);
});
it('Copy a folder with content - [C280219]', async () => {
await dataTable.selectItem(folder1);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationFav);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(folder1)).toBe(true, `${folder1} not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationFav);
expect(await dataTable.isItemPresent(folder1)).toBe(true, `${folder1} not present in destination folder`);
expect(await dataTable.isItemPresent(fileInFolder)).toBe(false, `${fileInFolder} is present in destination`);
await dataTable.doubleClickOnRowByName(folder1);
expect(await dataTable.isItemPresent(fileInFolder)).toBe(true, `${fileInFolder} is not present in parent folder`);
});
it('Copy multiple items - [C280225]', async () => {
await dataTable.selectMultipleItems([file2, file3]);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationFav);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 2 items');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(file2)).toBe(true, `${file2} not present in source folder`);
expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationFav);
expect(await dataTable.isItemPresent(file2)).toBe(true, `${file2} not present in destination folder`);
expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} not present in destination folder`);
});
it('Copy a file with a name that already exists on the destination - [C280220]', async () => {
await dataTable.selectItem(existingFile);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationFav);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(`${existingFile}.txt`)).toBe(true, `${existingFile}.txt not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationFav);
expect(await dataTable.isItemPresent(`${existingFile}.txt`)).toBe(true, `${existingFile}.txt not present in destination folder`);
expect(await dataTable.isItemPresent(`${existingFile}-1.txt`)).toBe(true, `${existingFile}-1.txt not present in destination folder`);
});
it('Copy a folder with a name that already exists on the destination - [C280221]', async () => {
await dataTable.selectItem(existingFolder);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('Personal Files');
await copyDialog.selectDestination(destinationFav);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 1 item');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(existingFolder)).toBe(true, `${existingFolder} not present in source folder`);
await page.clickPersonalFilesAndWait();
await dataTable.doubleClickOnRowByName(destinationFav);
expect(await dataTable.isItemPresent(existingFolder)).toBe(true, `${existingFolder} not present in destination folder`);
await dataTable.doubleClickOnRowByName(existingFolder);
expect(await dataTable.isItemPresent(file2InFolder)).toBe(true, `${file2InFolder} not present in destination folder`);
expect(await dataTable.isItemPresent(file3InFolder)).toBe(true, `${file3InFolder} not present in destination folder`);
});
it('Copy items into a library - [C291901]', async () => {
await dataTable.selectMultipleItems([file1, folder1], source);
await toolbar.clickMoreActionsCopy();
await copyDialog.selectLocation('File Libraries');
await copyDialog.doubleClickOnRow(siteName);
await copyDialog.doubleClickOnRow('documentLibrary');
await copyDialog.selectDestination(folderSiteFav);
await copyDialog.clickCopy();
const msg = await page.getSnackBarMessage();
expect(msg).toContain('Copied 2 items');
expect(msg).toContain('Undo');
await copyDialog.waitForDialogToClose();
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in source folder`);
expect(await dataTable.isItemPresent(folder1)).toBe(true, `${folder1} not present in source folder`);
await page.goToMyLibraries();
await dataTable.doubleClickOnRowByName(siteName);
await dataTable.doubleClickOnRowByName(folderSiteFav);
expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`);
expect(await dataTable.isItemPresent(folder1)).toBe(true, `${folder1} not present in destination folder`);
await dataTable.doubleClickOnRowByName(folder1);
expect(await dataTable.isItemPresent(fileInFolder)).toBe(true, `${fileInFolder} not present in parent folder`);
});
});
});

View File

@ -2,7 +2,7 @@
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
* Copyright (C) 2005 - 2019 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
@ -101,8 +101,8 @@ describe('Create folder', () => {
await createDialog.clickCreate();
await createDialog.waitForDialogToClose();
await dataTable.waitForHeader();
const isPresent = await dataTable.getRowByName(folderName1).isPresent();
expect(isPresent).toBe(true, 'Folder not displayed in list view');
expect(await dataTable.isItemPresent(folderName1)).toBe(true, 'Folder not displayed in list view');
});
it('creates new folder with name and description - [C216340]', async (done) => {
@ -114,7 +114,8 @@ describe('Create folder', () => {
await createDialog.clickCreate();
await createDialog.waitForDialogToClose();
await dataTable.waitForHeader();
expect(await dataTable.getRowByName(folderName2).isPresent()).toBe(true, 'Folder not displayed');
expect(await dataTable.isItemPresent(folderName2)).toBe(true, 'Folder not displayed');
const desc = await apis.user.nodes.getNodeDescription(folderName2, parentId);
expect(desc).toEqual(folderDescription);
done();
@ -124,17 +125,12 @@ describe('Create folder', () => {
await page.dataTable.doubleClickOnRowByName(parent);
await page.sidenav.openCreateFolderDialog();
await createDialog.waitForDialogToOpen();
const dialogTitle = await createDialog.getTitle();
const isFolderNameDisplayed = await createDialog.nameInput.isDisplayed();
const isDescriptionDisplayed = await createDialog.descriptionTextArea.isDisplayed();
const isCreateEnabled = await createDialog.createButton.isEnabled();
const isCancelEnabled = await createDialog.cancelButton.isEnabled();
expect(dialogTitle).toMatch('Create new folder');
expect(isFolderNameDisplayed).toBe(true, 'Name input is not displayed');
expect(isDescriptionDisplayed).toBe(true, 'Description field is not displayed');
expect(isCreateEnabled).toBe(false, 'Create button is not disabled');
expect(isCancelEnabled).toBe(true, 'Cancel button is not enabled');
expect(await createDialog.getTitle()).toMatch('Create new folder');
expect(await createDialog.isNameDisplayed()).toBe(true, 'Name input is not displayed');
expect(await createDialog.isDescriptionDisplayed()).toBe(true, 'Description field is not displayed');
expect(await createDialog.isCreateButtonEnabled()).toBe(false, 'Create button is not disabled');
expect(await createDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button is not enabled');
});
it('with empty folder name - [C216346]', async () => {
@ -142,11 +138,9 @@ describe('Create folder', () => {
await page.sidenav.openCreateFolderDialog();
await createDialog.waitForDialogToOpen();
await createDialog.deleteNameWithBackspace();
const isCreateEnabled = await createDialog.createButton.isEnabled();
const validationMessage = await createDialog.getValidationMessage();
expect(isCreateEnabled).toBe(false, 'Create button is enabled');
expect(validationMessage).toMatch('Folder name is required');
expect(await createDialog.isCreateButtonEnabled()).toBe(false, 'Create button is enabled');
expect(await createDialog.getValidationMessage()).toMatch('Folder name is required');
});
it('with folder name ending with a dot "." - [C216348]', async () => {
@ -154,11 +148,9 @@ describe('Create folder', () => {
await page.sidenav.openCreateFolderDialog();
await createDialog.waitForDialogToOpen();
await createDialog.enterName('folder-name.');
const isCreateEnabled = await createDialog.createButton.isEnabled();
const validationMessage = await createDialog.getValidationMessage();
expect(isCreateEnabled).toBe(false, 'Create button is not disabled');
expect(validationMessage).toMatch(`Folder name can't end with a period .`);
expect(await createDialog.isCreateButtonEnabled()).toBe(false, 'Create button is not disabled');
expect(await createDialog.getValidationMessage()).toMatch(`Folder name can't end with a period .`);
});
it('with folder name containing special characters - [C216347]', async () => {
@ -170,7 +162,7 @@ describe('Create folder', () => {
for (const name of namesWithSpecialChars) {
await createDialog.enterName(name);
expect(await createDialog.createButton.isEnabled()).toBe(false, 'Create button is not disabled');
expect(await createDialog.isCreateButtonEnabled()).toBe(false, 'Create button is not disabled');
expect(await createDialog.getValidationMessage()).toContain(`Folder name can't contain these characters`);
}
});
@ -180,11 +172,9 @@ describe('Create folder', () => {
await page.sidenav.openCreateFolderDialog();
await createDialog.waitForDialogToOpen();
await createDialog.enterName(' ');
const isCreateEnabled = await createDialog.createButton.isEnabled();
const validationMessage = await createDialog.getValidationMessage();
expect(isCreateEnabled).toBe(false, 'Create button is not disabled');
expect(validationMessage).toMatch(`Folder name can't contain only spaces`);
expect(await createDialog.isCreateButtonEnabled()).toBe(false, 'Create button is not disabled');
expect(await createDialog.getValidationMessage()).toMatch(`Folder name can't contain only spaces`);
});
it('cancel folder creation - [C216349]', async () => {
@ -194,6 +184,7 @@ describe('Create folder', () => {
await createDialog.enterName('test');
await createDialog.enterDescription('test description');
await createDialog.clickCancel();
expect(await createDialog.isDialogOpen()).not.toBe(true, 'dialog is not closed');
});
@ -203,8 +194,8 @@ describe('Create folder', () => {
await createDialog.waitForDialogToOpen();
await createDialog.enterName(duplicateFolderName);
await createDialog.clickCreate();
const message = await page.getSnackBarMessage();
expect(message).toEqual(`There's already a folder with this name. Try a different name.`);
expect(await page.getSnackBarMessage()).toEqual(`There's already a folder with this name. Try a different name.`);
expect(await createDialog.isDialogOpen()).toBe(true, 'dialog is not present');
});
@ -216,8 +207,8 @@ describe('Create folder', () => {
await createDialog.clickCreate();
await createDialog.waitForDialogToClose();
await dataTable.waitForHeader();
const isPresent = await dataTable.getRowByName(nameWithSpaces.trim()).isPresent();
expect(isPresent).toBe(true, 'Folder not displayed in list view');
expect(await dataTable.isItemPresent(nameWithSpaces.trim())).toBe(true, 'Folder not displayed in list view');
});
});
@ -225,7 +216,7 @@ describe('Create folder', () => {
const fileLibrariesPage = new BrowsingPage();
beforeEach(async (done) => {
await fileLibrariesPage.clickFileLibrariesAndWait();
await fileLibrariesPage.goToMyLibrariesAndWait();
done();
});
@ -243,7 +234,8 @@ describe('Create folder', () => {
await createDialog.clickCreate();
await createDialog.waitForDialogToClose();
await dataTable.waitForHeader();
expect(await dataTable.getRowByName(folderSite).isPresent()).toBe(true, 'Folder not displayed');
expect(await dataTable.isItemPresent(folderSite)).toBe(true, 'Folder not displayed');
const desc = await apis.user.nodes.getNodeDescription(folderSite, docLibUserSite);
expect(desc).toEqual(folderDescription);
});
@ -255,6 +247,7 @@ describe('Create folder', () => {
await createDialog.enterName('test');
await createDialog.enterDescription('test description');
await createDialog.clickCancel();
expect(await createDialog.isDialogOpen()).not.toBe(true, 'dialog is not closed');
});
@ -264,11 +257,10 @@ describe('Create folder', () => {
await createDialog.waitForDialogToOpen();
await createDialog.enterName(duplicateFolderSite);
await createDialog.clickCreate();
const message = await page.getSnackBarMessage();
expect(message).toEqual(`There's already a folder with this name. Try a different name.`);
expect(await page.getSnackBarMessage()).toEqual(`There's already a folder with this name. Try a different name.`);
expect(await createDialog.isDialogOpen()).toBe(true, 'dialog is not present');
});
});
xit('');
});

Some files were not shown because too many files have changed in this diff Show More