From c8b99b9d296a647230507594284f1a6ffbf4bedc Mon Sep 17 00:00:00 2001 From: Denys Vuika Date: Fri, 22 Mar 2019 14:51:40 +0000 Subject: [PATCH] 1.7.0 (#1037) * 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 * 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 * [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 --- .gitignore | 1 + .travis.yml | 4 +- .vscode/extensions.json | 12 + .vscode/settings.json | 3 + .vscode/typescript.code-snippets | 19 + Dockerfile | 37 +- README.md | 127 +- angular.json | 69 +- build-tomcat-e2e.sh | 2 +- cspell.json | 9 +- docker-compose-keycloak.yml | 146 + docker-compose.yml | 25 +- docker-compose/README.md | 15 - docker-compose/docker-compose.yml | 94 - docker-compose/nginx.conf | 45 - docker/auth/alfresco-realm.json | 1673 ++ docker-entrypoint.sh => docker/entrypoint.sh | 4 - docker/nginx.conf | 31 + docker/proxy/nginx.conf | 29 + docs/README.md | 20 +- docs/abn-tree.yml | 44 + docs/extending/README.md | 2 + docs/extending/actions.md | 3 + docs/extending/application-actions.md | 95 +- docs/extending/application-features.md | 189 +- docs/extending/components.md | 1 + docs/extending/creating-custom-evaluators.md | 11 +- docs/extending/extensibility-features.md | 1 + docs/extending/extension-format.md | 23 +- docs/extending/icons.md | 4 + docs/extending/redistributable-libraries.md | 13 +- docs/extending/registration.md | 10 +- docs/extending/routes.md | 5 +- docs/extending/rules.md | 103 +- docs/extending/tutorials.md | 3 + docs/features/README.md | 2 + docs/features/document-list-layout.md | 135 +- docs/features/file-viewer.md | 7 +- docs/features/header.md | 13 +- docs/features/info-drawer.md | 13 +- docs/features/search-results.md | 45 +- docs/features/side-navigation.md | 8 +- docs/features/user-interface-layout.md | 3 +- docs/features/version-manager.md | 7 +- docs/getting-started/README.md | 5 +- docs/getting-started/building-from-source.md | 14 +- docs/getting-started/configuration.md | 36 +- docs/getting-started/cors.md | 2 + docs/getting-started/docker.md | 20 +- docs/getting-started/internationalization.md | 5 +- docs/getting-started/navigation.md | 5 +- docs/getting-started/prerequisites.md | 5 +- docs/getting-started/sso.md | 59 + docs/help.md | 2 +- docs/images/aca-sso-settings.png | Bin 0 -> 106750 bytes docs/tutorials/README.md | 2 + .../tutorials/custom-route-with-parameters.md | 1 + docs/tutorials/dialog-actions.md | 1 + docs/tutorials/introduction-to-extending.md | 3 +- e2e/components/breadcrumb/breadcrumb.ts | 2 +- e2e/components/component.ts | 2 +- e2e/components/components.ts | 2 +- e2e/components/data-table/data-table.ts | 109 +- .../datetime-picker/datetime-picker.ts | 2 +- e2e/components/dialog/confirm-dialog.ts | 45 +- e2e/components/dialog/copy-move-dialog.ts | 13 +- .../dialog/create-edit-folder-dialog.ts | 33 +- .../dialog/create-library-dialog.ts | 4 +- .../dialog/manage-versions-dialog.ts | 2 +- e2e/components/dialog/share-dialog.ts | 8 +- .../dialog/upload-new-version-dialog.ts | 121 + e2e/components/header/header.ts | 49 +- e2e/components/header/user-info.ts | 8 +- e2e/components/info-drawer/info-drawer.ts | 287 +- e2e/components/login/login.ts | 47 +- e2e/components/menu/menu.ts | 189 +- e2e/components/metadata-card/metadata-card.ts | 2 +- e2e/components/pagination/pagination.ts | 62 +- e2e/components/search/search-input.ts | 35 +- e2e/components/sidenav/sidenav.ts | 65 +- e2e/components/toolbar/toolbar.ts | 171 +- e2e/components/viewer/viewer.ts | 8 +- e2e/configs.ts | 15 +- e2e/pages/browsing-page.ts | 74 +- e2e/pages/login-page.ts | 2 +- e2e/pages/page.ts | 10 +- e2e/pages/pages.ts | 2 +- e2e/pages/search-results-page.ts | 8 +- .../context-submenus-ext.json | 225 +- .../document-presets-ext.json | 225 +- .../extensions-default.json | 219 +- .../extensibility-configs/header-ext.json | 219 +- .../extensibility-configs/metadata-ext.json | 219 +- .../extensibility-configs/viewer-ext.json | 227 +- e2e/resources/test-files/file2-docx.docx | Bin 0 -> 11523 bytes e2e/resources/test-files/file2-xlsx.xlsx | Bin 0 -> 97629 bytes .../context-menu-multiple-selection.test.ts | 575 +- .../context-menu-single-selection.test.ts | 593 +- e2e/suites/actions/copy.test.ts | 556 + e2e/suites/actions/create-folder.test.ts | 66 +- e2e/suites/actions/create-library.test.ts | 52 +- e2e/suites/actions/delete-undo-delete.test.ts | 636 +- e2e/suites/actions/download.test.ts | 315 + e2e/suites/actions/edit-folder.test.ts | 87 +- e2e/suites/actions/edit-offline.test.ts | 270 + e2e/suites/actions/library-actions.test.ts | 72 +- e2e/suites/actions/mark-favorite.test.ts | 939 +- e2e/suites/actions/move.test.ts | 714 + e2e/suites/actions/new-menu.test.ts | 53 +- e2e/suites/actions/permanently-delete.test.ts | 54 +- e2e/suites/actions/restore.test.ts | 54 +- e2e/suites/actions/share-file.test.ts | 201 +- e2e/suites/actions/single-click.test.ts | 4 +- ...cial-permissions-available-actions.test.ts | 2180 ++- .../toolbar-multiple-selection.test.ts | 642 +- .../actions/toolbar-single-selection.test.ts | 600 +- e2e/suites/actions/unshare-file.test.ts | 143 +- e2e/suites/actions/upload-file.test.ts | 2 +- e2e/suites/actions/upload-new-version.test.ts | 672 + e2e/suites/application/general.test.ts | 6 +- e2e/suites/application/page-titles.test.ts | 37 +- e2e/suites/authentication/login.test.ts | 23 +- e2e/suites/authentication/logout.test.ts | 4 +- .../extensions/ext-context-submenus.test.ts | 2 +- .../extensions/ext-document-list.test.ts | 26 +- e2e/suites/extensions/ext-header.test.ts | 2 +- e2e/suites/extensions/ext-info-drawer.test.ts | 16 +- e2e/suites/extensions/ext-metadata.test.ts | 4 +- e2e/suites/extensions/ext-viewer.test.ts | 8 +- e2e/suites/info-drawer/comments.test.ts | 398 + e2e/suites/info-drawer/general.test.ts | 90 + .../info-drawer/library-properties.test.ts | 76 +- e2e/suites/list-views/empty-list.test.ts | 100 +- e2e/suites/list-views/favorites.test.ts | 26 +- e2e/suites/list-views/file-libraries.test.ts | 80 +- e2e/suites/list-views/generic-errors.test.ts | 2 +- e2e/suites/list-views/permissions.test.ts | 10 +- e2e/suites/list-views/personal-files.test.ts | 24 +- e2e/suites/list-views/recent-files.test.ts | 28 +- e2e/suites/list-views/shared-files.test.ts | 24 +- e2e/suites/list-views/tooltips.test.ts | 4 +- e2e/suites/list-views/trash.test.ts | 50 +- e2e/suites/navigation/breadcrumb.test.ts | 13 +- e2e/suites/navigation/sidebar.test.ts | 154 +- e2e/suites/pagination/pag-favorites.test.ts | 56 +- .../pagination/pag-file-libraries.test.ts | 294 +- .../pagination/pag-personal-files.test.ts | 54 +- .../pagination/pag-recent-files.test.ts | 56 +- .../pagination/pag-search-results.test.ts | 50 +- .../pagination/pag-shared-files.test.ts | 56 +- e2e/suites/pagination/pag-single-page.test.ts | 25 +- e2e/suites/pagination/pag-trash.test.ts | 56 +- e2e/suites/search/search-input.test.ts | 9 +- .../search/search-results-libraries.test.ts | 74 +- e2e/suites/search/search-results.test.ts | 34 +- e2e/suites/viewer/viewer-actions.test.ts | 770 +- e2e/suites/viewer/viewer-general.test.ts | 9 +- e2e/tsconfig.e2e.typecheck.json | 7 + e2e/utilities/browser-utils.ts | 2 +- .../apis/authentication/authentication-api.ts | 2 +- .../repo-client/apis/comments/comments-api.ts | 31 +- .../apis/favorites/favorites-api.ts | 39 +- .../apis/nodes/node-body-create.ts | 2 +- .../apis/nodes/node-content-tree.ts | 2 +- .../repo-client/apis/nodes/nodes-api.ts | 87 +- .../apis/people/people-api-models.ts | 2 +- .../repo-client/apis/people/people-api.ts | 10 +- .../repo-client/apis/queries/queries-api.ts | 37 +- e2e/utilities/repo-client/apis/repo-api.ts | 17 +- .../repo-client/apis/search/search-api.ts | 52 +- .../apis/shared-links/shared-links-api.ts | 10 +- .../repo-client/apis/sites/sites-api.ts | 26 +- .../repo-client/apis/trashcan/trashcan-api.ts | 10 +- .../repo-client/apis/upload/upload-api.ts | 8 +- .../repo-client/repo-client-models.ts | 2 +- e2e/utilities/repo-client/repo-client.ts | 7 +- .../reporters/console/console-logger.ts | 2 +- e2e/utilities/reporters/console/console.ts | 2 +- e2e/utilities/utils.ts | 71 +- extension.schema.json | 22 +- nginx.conf | 27 - package-lock.json | 13070 ++++++---------- package.json | 125 +- projects/adf-office-services-ext/LICENSE | 177 + projects/adf-office-services-ext/README.md | 72 + .../assets/aos.plugin.json | 75 + .../assets/i18n/ar.json | 5 + .../assets/i18n/cs.json | 5 + .../assets/i18n/da.json | 5 + .../assets/i18n/de.json | 5 + .../assets/i18n/en.json | 5 + .../assets/i18n/es.json | 5 + .../assets/i18n/fi.json | 5 + .../assets/i18n/fr.json | 5 + .../assets/i18n/it.json | 5 + .../assets/i18n/ja.json | 5 + .../assets/i18n/nb.json | 5 + .../assets/i18n/nl.json | 5 + .../assets/i18n/pl.json | 5 + .../assets/i18n/pt-BR.json | 5 + .../assets/i18n/ru.json | 5 + .../assets/i18n/sv.json | 5 + .../assets/i18n/zh-CN.json | 5 + .../adf-office-services-ext/karma.conf.js | 34 + .../adf-office-services-ext/ng-package.json | 14 + projects/adf-office-services-ext/ngi.json | 20 + projects/adf-office-services-ext/package.json | 26 + .../src/lib/actions/aos.actions.ts | 9 + .../src/lib/aos-extension.module.ts | 25 + .../src/lib/aos-extension.service.ts | 129 + .../src/lib/effects/aos.effects.ts | 24 + .../src/lib/evaluators.spec.ts | 230 + .../src/lib/evaluators.ts | 84 + .../src/lib/utils.spec.ts | 15 + .../adf-office-services-ext/src/lib/utils.ts | 37 + .../adf-office-services-ext/src/public_api.ts | 5 + projects/adf-office-services-ext/src/test.ts | 22 + .../adf-office-services-ext/tsconfig.lib.json | 32 + .../tsconfig.spec.json | 17 + projects/adf-office-services-ext/tslint.json | 17 + protractor.conf.js | 44 +- scripts/update-version.sh | 107 +- src/app.config.json | 41 +- src/app/app.component.spec.ts | 48 +- src/app/app.component.ts | 27 +- src/app/app.module.ts | 21 +- src/app/app.routes.strategy.spec.ts | 88 + src/app/app.routes.strategy.ts | 20 +- src/app/app.routes.ts | 2 +- .../components/about/about.component.spec.ts | 2 +- src/app/components/about/about.component.ts | 4 +- src/app/components/about/about.module.ts | 2 +- .../extension-list.component.ts | 2 +- .../license-list/license-list.component.ts | 2 +- .../module-list/module-list.component.ts | 4 +- .../package-list/package-list.component.ts | 2 +- .../status-list/status-list.component.ts | 2 +- src/app/components/common/common.module.ts | 48 +- .../dynamic-column.component.ts | 108 - .../generic-error.component.html | 2 +- .../generic-error.component.spec.ts | 2 +- .../generic-error/generic-error.component.ts | 2 +- .../common/icon/icon.component.html | 7 - .../common/icon/icon.component.scss | 4 - .../library-name-column.component.spec.ts | 102 - .../library-name-column.component.ts | 98 - .../library-role-column.component.spec.ts | 83 - .../library-role-column.component.ts | 65 - .../library-status-column.component.spec.ts | 32 - .../library-status-column.component.ts | 63 - .../location-link.component.spec.ts | 2 +- .../location-link/location-link.component.ts | 4 +- .../name-column/name-column.component.ts | 73 - .../trashcan-name-column.component.spec.ts | 114 - .../trashcan-name-column.component.ts | 95 - .../context-menu-item.component.spec.ts | 2 +- .../context-menu-item.component.ts | 2 +- ...ntext-menu-outside-event.directive.spec.ts | 2 +- .../context-menu/context-menu-overlay.ts | 2 +- .../context-menu.component.spec.ts | 2 +- .../context-menu/context-menu.component.ts | 2 +- .../context-menu/context-menu.directive.ts | 4 +- .../context-menu.directives.spec.ts | 2 +- .../context-menu/context-menu.module.ts | 2 +- .../context-menu/context-menu.service.spec.ts | 12 +- src/app/components/context-menu/interfaces.ts | 2 +- .../create-menu/create-menu.component.html | 27 +- .../create-menu/create-menu.component.spec.ts | 2 +- .../create-menu/create-menu.component.ts | 2 +- .../create-menu/create-menu.module.ts | 2 +- .../current-user/current-user.component.html | 27 +- .../current-user.component.spec.ts | 2 +- .../current-user/current-user.component.ts | 9 +- .../current-user/current-user.module.ts | 2 +- ...document-list-custom-components.module.ts} | 45 +- .../locked-by/locked-by.component.scss | 11 + .../locked-by/locked-by.component.ts | 61 + .../name-column/name-column.component.scss | 14 + .../name-column/name-column.component.spec.ts | 108 + .../name-column/name-column.component.ts | 90 + .../favorite-libraries.component.html | 154 +- .../favorite-libraries.component.spec.ts | 12 +- .../favorite-libraries.component.ts | 4 +- .../favorites/favorites.component.html | 127 +- .../favorites/favorites.component.spec.ts | 49 +- .../favorites/favorites.component.ts | 24 +- .../components/favorites/favorites.module.ts | 2 +- src/app/components/files/files.component.html | 114 +- .../components/files/files.component.spec.ts | 87 +- src/app/components/files/files.component.ts | 22 +- .../components/header/header.component.html | 11 +- .../header/header.component.spec.ts | 2 +- src/app/components/header/header.component.ts | 2 +- src/app/components/header/header.module.ts | 2 +- .../comments-tab.component.spec.ts | 87 +- .../comments-tab/comments-tab.component.ts | 19 +- .../info-drawer/info-drawer.component.html | 25 +- .../info-drawer/info-drawer.component.spec.ts | 20 +- .../info-drawer/info-drawer.component.ts | 53 +- .../info-drawer/info.drawer.module.ts | 2 +- .../library-metadata-form.component.html | 243 +- .../library-metadata-form.component.spec.ts | 4 +- .../library-metadata-form.component.ts | 8 +- .../library-metadata-tab.component.ts | 4 +- .../metadata-tab.component.spec.ts | 2 +- .../metadata-tab/metadata-tab.component.ts | 25 +- .../versions-tab.component.spec.ts | 2 +- .../versions-tab/versions-tab.component.ts | 8 +- .../app-layout/app-layout.component.html | 71 +- .../app-layout/app-layout.component.spec.ts | 37 +- .../layout/app-layout/app-layout.component.ts | 13 +- src/app/components/layout/layout.module.ts | 4 +- .../page-layout-content.component.ts | 2 +- .../page-layout-error.component.ts | 2 +- .../page-layout-header.component.ts | 2 +- .../page-layout/page-layout.component.ts | 2 +- .../libraries/libraries.component.html | 141 +- .../libraries/libraries.component.spec.ts | 10 +- .../libraries/libraries.component.ts | 4 +- src/app/components/login/login.component.html | 13 +- .../components/login/login.component.spec.ts | 2 +- src/app/components/login/login.component.ts | 2 +- src/app/components/login/login.module.ts | 2 +- .../node-version-form.component.html | 27 + .../node-version-form.component.scss | 24 + .../node-version-form.component.spec.ts | 68 + .../node-version-form.component.ts | 85 + .../node-version/node-version.module.ts | 57 + src/app/components/page.component.spec.ts | 2 +- src/app/components/page.component.ts | 41 +- .../node-permissions.dialog.html | 6 +- .../node-permissions.dialog.spec.ts | 2 +- .../node-permissions.dialog.ts | 2 +- .../permission-manager.component.html | 32 +- .../permission-manager.component.spec.ts | 2 +- .../permission-manager.component.ts | 4 +- .../permissions/permissions.module.ts | 2 +- .../preview-extension.component.spec.ts | 2 +- .../preview/preview-extension.component.ts | 4 +- .../components/preview/preview.component.html | 96 +- .../components/preview/preview.component.scss | 23 +- .../preview/preview.component.spec.ts | 55 +- .../components/preview/preview.component.ts | 33 +- src/app/components/preview/preview.module.ts | 2 +- .../recent-files/recent-files.component.html | 123 +- .../recent-files.component.spec.ts | 48 +- .../recent-files/recent-files.component.ts | 25 +- .../recent-files/recent-files.module.ts | 2 +- .../search-input-control.component.html | 51 +- .../search-input-control.component.spec.ts | 2 +- .../search-input-control.component.ts | 2 +- .../components/search/search-input.module.ts | 2 +- .../search-input/search-input.component.html | 91 +- .../search-input.component.spec.ts | 2 +- .../search-input/search-input.component.ts | 84 +- ...ch-libraries-query-builder.service.spec.ts | 2 +- .../search-libraries-query-builder.service.ts | 4 +- .../search-libraries-results.component.html | 185 +- .../search-libraries-results.component.ts | 4 +- .../search-results-row.component.html | 25 +- .../search-results-row.component.ts | 4 +- .../search-results-row.components.spec.ts | 2 +- .../search/search-results.module.ts | 2 +- .../search-results.component.html | 162 +- .../search-results.component.spec.ts | 286 +- .../search-results.component.ts | 129 +- .../settings/settings.component.html | 151 +- .../settings/settings.component.spec.ts | 2 +- .../components/settings/settings.component.ts | 63 +- .../components/settings/settings.module.ts | 2 +- .../shared-files/shared-files.component.html | 143 +- .../shared-files.component.spec.ts | 47 +- .../shared-files/shared-files.component.ts | 14 +- .../shared-files/shared-files.module.ts | 2 +- .../shared-link-view.component.html | 19 +- .../shared-link-view.component.scss | 4 + .../shared-link-view.component.spec.ts | 104 +- .../shared-link-view.component.ts | 45 +- .../shared-link-view.module.ts | 4 +- .../content-node-share.dialog.html | 155 +- .../content-node-share.dialog.scss | 6 +- .../content-node-share.dialog.spec.ts | 6 +- .../content-node-share.dialog.ts | 6 +- .../content-node-share.module.ts | 2 +- src/app/components/shared/shared.module.ts | 2 +- .../toggle-shared.component.html | 2 +- .../toggle-shared.component.spec.ts | 2 +- .../toggle-shared/toggle-shared.component.ts | 2 +- .../toggle-shared/toggle-shared.module.ts | 2 +- .../sidenav/expansion-panel.directive.spec.ts | 2 +- .../sidenav/expansion-panel.directive.ts | 2 +- .../components/sidenav/sidenav.component.html | 357 +- .../sidenav/sidenav.component.spec.ts | 42 +- .../sidenav/sidenav.component.theme.scss | 4 + .../components/sidenav/sidenav.component.ts | 2 +- src/app/components/sidenav/sidenav.module.ts | 2 +- .../document-display-mode.component.spec.ts | 2 +- .../document-display-mode.component.ts | 2 +- .../toggle-edit-offline.component.spec.ts | 147 + .../toggle-edit-offline.component.ts | 100 + .../toggle-favorite-library.component.spec.ts | 4 +- .../toggle-favorite-library.component.ts | 10 +- .../toggle-favorite.component.spec.ts | 2 +- .../toggle-favorite.component.ts | 17 +- .../toggle-info-drawer.component.spec.ts | 2 +- .../toggle-info-drawer.component.ts | 2 +- .../toggle-join-library-button.component.ts | 2 +- .../toggle-join-library-menu.component.ts | 2 +- .../toggle-join-library.component.spec.ts | 2 +- .../toolbar-action.component.html | 20 +- .../toolbar-action.component.spec.ts | 2 +- .../toolbar-action.component.ts | 2 +- .../toolbar-button.component.spec.ts | 2 +- .../toolbar-button.component.ts | 2 +- .../toolbar-menu-item.component.spec.ts | 2 +- .../toolbar-menu-item.component.ts | 2 +- .../toolbar-menu.component.spec.ts | 2 +- .../toolbar-menu/toolbar-menu.component.ts | 2 +- src/app/components/toolbar/toolbar.module.ts | 6 +- .../trashcan/trashcan.component.html | 132 +- .../trashcan/trashcan.component.spec.ts | 43 +- .../components/trashcan/trashcan.component.ts | 5 +- .../components/trashcan/trashcan.module.ts | 2 +- .../file-uploading-dialog.component.html | 227 +- .../file-uploading-dialog.component.ts | 179 +- .../file-uploading-list-row.component.html | 170 +- .../file-uploading-list-row.component.ts | 45 +- .../file-uploading-list.component.html | 7 +- .../file-uploading-list.component.ts | 64 +- ...load-dialog.module.ts => upload.module.ts} | 23 +- src/app/dialogs/library/library.dialog.html | 90 - src/app/dialogs/library/library.dialog.scss | 29 - .../dialogs/library/library.dialog.spec.ts | 248 - src/app/dialogs/library/library.dialog.ts | 262 - .../node-version-upload.dialog.html | 20 + .../node-version-upload.dialog.scss | 15 + .../node-version-upload.dialog.spec.ts | 77 + .../node-version-upload.dialog.ts} | 16 +- .../node-versions/node-versions.dialog.html | 21 +- .../node-versions.dialog.spec.ts | 2 +- .../node-versions/node-versions.dialog.ts | 4 +- src/app/directives/directives.module.ts | 8 +- .../document-list.directive.spec.ts | 2 +- src/app/directives/document-list.directive.ts | 79 +- src/app/directives/experimental.directive.ts | 105 - .../library-favorite.directive.spec.ts | 8 +- .../directives/library-favorite.directive.ts | 6 +- .../library-membership.directive.spec.ts | 2 +- .../library-membership.directive.ts | 4 +- .../directives/lock-node.directive.spec.ts | 147 + src/app/directives/lock-node.directive.ts | 102 + .../directives/pagination.directive.spec.ts | 2 +- src/app/directives/pagination.directive.ts | 2 +- src/app/extensions.module.ts | 3 +- src/app/extensions/app.interface.ts | 9 +- src/app/extensions/core.extensions.module.ts | 29 +- .../extensions/document-list.extensions.ts | 2 +- .../evaluators/app.evaluators.spec.ts | 355 + .../extensions/evaluators/app.evaluators.ts | 196 +- .../evaluators/navigation.evaluators.spec.ts | 338 + .../evaluators/navigation.evaluators.ts | 122 +- .../evaluators/repository.evaluators.ts | 8 +- src/app/extensions/extension.service.spec.ts | 65 +- src/app/extensions/extension.service.ts | 104 +- src/app/extensions/icon.extensions.ts | 2 +- src/app/guards/auth.guard.spec.ts | 26 +- src/app/guards/auth.guard.ts | 13 +- src/app/guards/shared.guard.ts | 2 +- src/app/material.module.ts | 2 +- src/app/services/app.service.spec.ts | 96 + src/app/services/app.service.ts | 31 +- src/app/services/content-api.service.spec.ts | 2 +- src/app/services/content-api.service.ts | 20 +- .../content-management.service.spec.ts | 298 +- .../services/content-management.service.ts | 100 +- src/app/services/data.service.ts | 4 +- .../services/experimental-guard.service.ts | 35 - src/app/services/node-actions.service.spec.ts | 10 +- src/app/services/node-actions.service.ts | 26 +- .../services/node-permission.service.spec.ts | 2 +- src/app/services/node-permission.service.ts | 73 +- src/app/store/actions.ts | 3 +- src/app/store/actions/app.actions.ts | 10 +- src/app/store/actions/favorite.actions.ts | 4 +- src/app/store/actions/info-drawer.actions.ts | 2 +- src/app/store/actions/library.actions.ts | 4 +- src/app/store/actions/modals.actions.ts | 2 +- src/app/store/actions/node.actions.ts | 28 +- src/app/store/actions/repository.actions.ts | 13 +- src/app/store/actions/router.actions.ts | 4 +- src/app/store/actions/search.actions.ts | 17 +- src/app/store/actions/snackbar.actions.ts | 2 +- src/app/store/actions/upload.actions.ts | 7 +- src/app/store/actions/viewer.actions.ts | 4 +- src/app/store/app-store.module.ts | 2 +- src/app/store/effects.ts | 3 +- src/app/store/effects/app.effects.ts | 21 +- src/app/store/effects/download.effects.ts | 23 +- src/app/store/effects/favorite.effects.ts | 2 +- src/app/store/effects/library.effects.ts | 5 +- src/app/store/effects/modals.effects.ts | 2 +- src/app/store/effects/node.effects.spec.ts | 65 +- src/app/store/effects/node.effects.ts | 29 +- src/app/store/effects/router.effects.ts | 4 +- src/app/store/effects/search.effects.spec.ts | 78 + src/app/store/effects/search.effects.ts | 12 +- src/app/store/effects/snackbar.effects.ts | 2 +- src/app/store/effects/upload.effects.spec.ts | 172 + src/app/store/effects/upload.effects.ts | 109 +- src/app/store/effects/viewer.effects.ts | 6 +- src/app/store/models.ts | 2 +- src/app/store/models/delete-status.model.ts | 2 +- .../store/models/deleted-node-info.model.ts | 2 +- src/app/store/models/node-info.model.ts | 2 +- src/app/store/reducers/app.reducer.ts | 60 +- src/app/store/selectors/app.selectors.ts | 9 +- src/app/store/states.ts | 2 +- src/app/store/states/app.state.ts | 16 +- src/app/testing/app-testing.module.ts | 10 +- src/app/testing/translate-pipe.directive.ts | 2 +- src/app/testing/translation.service.ts | 2 +- src/app/ui/custom-theme.scss | 2 - .../adf-content-node-selector.theme.scss | 7 - .../ui/overrides/adf-document-list.theme.scss | 26 +- .../ui/overrides/adf-layout-header.theme.scss | 36 - .../ui/overrides/adf-search-filter.theme.scss | 12 + .../overrides/adf-sidenav-layout.theme.scss | 10 +- src/app/ui/overrides/adf-toolbar.theme.scss | 4 + .../ui/overrides/adf-upload-dialog.theme.scss | 24 +- .../overrides/adf-upload-drag-area.theme.scss | 10 +- .../node.utils.ts} | 32 +- src/assets/app.extensions.json | 687 +- src/assets/i18n/ar.json | 487 + src/assets/i18n/cs.json | 487 + src/assets/i18n/da.json | 487 + src/assets/i18n/de.json | 51 +- src/assets/i18n/en.json | 54 +- src/assets/i18n/es.json | 77 +- src/assets/i18n/fi.json | 487 + src/assets/i18n/fr.json | 51 +- src/assets/i18n/it.json | 51 +- src/assets/i18n/ja.json | 51 +- src/assets/i18n/nb.json | 51 +- src/assets/i18n/nl.json | 51 +- src/assets/i18n/pl.json | 487 + src/assets/i18n/pt-BR.json | 51 +- src/assets/i18n/ru.json | 51 +- src/assets/i18n/sv.json | 487 + src/assets/i18n/zh-CN.json | 51 +- src/assets/images/baseline-lock-24px.svg | 1 + src/assets/images/ic_lock_black_24dp_1x.png | Bin 205 -> 0 bytes src/environments/environment.e2e.ts | 2 +- src/environments/environment.prod.ts | 2 +- src/environments/environment.ts | 2 +- src/index.html | 74 +- src/main.ts | 2 +- src/polyfills.ts | 2 +- src/test.ts | 2 +- src/typings.d.ts | 2 +- src/versions.json | 5783 ------- start-sso.sh | 19 + tsconfig.json | 9 +- 562 files changed, 30932 insertions(+), 23739 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/typescript.code-snippets create mode 100644 docker-compose-keycloak.yml delete mode 100644 docker-compose/README.md delete mode 100644 docker-compose/docker-compose.yml delete mode 100644 docker-compose/nginx.conf create mode 100644 docker/auth/alfresco-realm.json rename docker-entrypoint.sh => docker/entrypoint.sh (94%) create mode 100644 docker/nginx.conf create mode 100644 docker/proxy/nginx.conf create mode 100644 docs/abn-tree.yml create mode 100644 docs/getting-started/sso.md create mode 100644 docs/images/aca-sso-settings.png create mode 100755 e2e/components/dialog/upload-new-version-dialog.ts create mode 100644 e2e/resources/test-files/file2-docx.docx create mode 100644 e2e/resources/test-files/file2-xlsx.xlsx create mode 100755 e2e/suites/actions/copy.test.ts create mode 100755 e2e/suites/actions/download.test.ts create mode 100755 e2e/suites/actions/edit-offline.test.ts create mode 100755 e2e/suites/actions/move.test.ts create mode 100755 e2e/suites/actions/upload-new-version.test.ts create mode 100755 e2e/suites/info-drawer/comments.test.ts create mode 100755 e2e/suites/info-drawer/general.test.ts create mode 100644 e2e/tsconfig.e2e.typecheck.json rename src/app/components/common/name-column/name-column.component.spec.ts => e2e/utilities/repo-client/apis/comments/comments-api.ts (56%) mode change 100644 => 100755 delete mode 100644 nginx.conf create mode 100644 projects/adf-office-services-ext/LICENSE create mode 100644 projects/adf-office-services-ext/README.md create mode 100644 projects/adf-office-services-ext/assets/aos.plugin.json create mode 100644 projects/adf-office-services-ext/assets/i18n/ar.json create mode 100644 projects/adf-office-services-ext/assets/i18n/cs.json create mode 100644 projects/adf-office-services-ext/assets/i18n/da.json create mode 100644 projects/adf-office-services-ext/assets/i18n/de.json create mode 100644 projects/adf-office-services-ext/assets/i18n/en.json create mode 100644 projects/adf-office-services-ext/assets/i18n/es.json create mode 100644 projects/adf-office-services-ext/assets/i18n/fi.json create mode 100644 projects/adf-office-services-ext/assets/i18n/fr.json create mode 100644 projects/adf-office-services-ext/assets/i18n/it.json create mode 100644 projects/adf-office-services-ext/assets/i18n/ja.json create mode 100644 projects/adf-office-services-ext/assets/i18n/nb.json create mode 100644 projects/adf-office-services-ext/assets/i18n/nl.json create mode 100644 projects/adf-office-services-ext/assets/i18n/pl.json create mode 100644 projects/adf-office-services-ext/assets/i18n/pt-BR.json create mode 100644 projects/adf-office-services-ext/assets/i18n/ru.json create mode 100644 projects/adf-office-services-ext/assets/i18n/sv.json create mode 100644 projects/adf-office-services-ext/assets/i18n/zh-CN.json create mode 100644 projects/adf-office-services-ext/karma.conf.js create mode 100644 projects/adf-office-services-ext/ng-package.json create mode 100644 projects/adf-office-services-ext/ngi.json create mode 100644 projects/adf-office-services-ext/package.json create mode 100755 projects/adf-office-services-ext/src/lib/actions/aos.actions.ts create mode 100644 projects/adf-office-services-ext/src/lib/aos-extension.module.ts create mode 100644 projects/adf-office-services-ext/src/lib/aos-extension.service.ts create mode 100755 projects/adf-office-services-ext/src/lib/effects/aos.effects.ts create mode 100644 projects/adf-office-services-ext/src/lib/evaluators.spec.ts create mode 100644 projects/adf-office-services-ext/src/lib/evaluators.ts create mode 100644 projects/adf-office-services-ext/src/lib/utils.spec.ts create mode 100644 projects/adf-office-services-ext/src/lib/utils.ts create mode 100644 projects/adf-office-services-ext/src/public_api.ts create mode 100644 projects/adf-office-services-ext/src/test.ts create mode 100644 projects/adf-office-services-ext/tsconfig.lib.json create mode 100644 projects/adf-office-services-ext/tsconfig.spec.json create mode 100644 projects/adf-office-services-ext/tslint.json create mode 100644 src/app/app.routes.strategy.spec.ts delete mode 100644 src/app/components/common/dynamic-column/dynamic-column.component.ts delete mode 100644 src/app/components/common/icon/icon.component.html delete mode 100644 src/app/components/common/icon/icon.component.scss delete mode 100644 src/app/components/common/library-name-column/library-name-column.component.spec.ts delete mode 100644 src/app/components/common/library-name-column/library-name-column.component.ts delete mode 100644 src/app/components/common/library-role-column/library-role-column.component.spec.ts delete mode 100644 src/app/components/common/library-role-column/library-role-column.component.ts delete mode 100644 src/app/components/common/library-status-column/library-status-column.component.spec.ts delete mode 100644 src/app/components/common/library-status-column/library-status-column.component.ts delete mode 100644 src/app/components/common/name-column/name-column.component.ts delete mode 100644 src/app/components/common/trashcan-name-column/trashcan-name-column.component.spec.ts delete mode 100644 src/app/components/common/trashcan-name-column/trashcan-name-column.component.ts rename src/app/components/{common/icon/icon.component.ts => dl-custom-components/document-list-custom-components.module.ts} (59%) create mode 100644 src/app/components/dl-custom-components/locked-by/locked-by.component.scss create mode 100644 src/app/components/dl-custom-components/locked-by/locked-by.component.ts create mode 100644 src/app/components/dl-custom-components/name-column/name-column.component.scss create mode 100644 src/app/components/dl-custom-components/name-column/name-column.component.spec.ts create mode 100644 src/app/components/dl-custom-components/name-column/name-column.component.ts create mode 100644 src/app/components/node-version/node-version-form.component.html create mode 100644 src/app/components/node-version/node-version-form.component.scss create mode 100644 src/app/components/node-version/node-version-form.component.spec.ts create mode 100644 src/app/components/node-version/node-version-form.component.ts create mode 100644 src/app/components/node-version/node-version.module.ts create mode 100644 src/app/components/toolbar/toggle-edit-offline/toggle-edit-offline.component.spec.ts create mode 100644 src/app/components/toolbar/toggle-edit-offline/toggle-edit-offline.component.ts rename src/app/components/upload-dialog/{upload-dialog.module.ts => upload.module.ts} (66%) delete mode 100644 src/app/dialogs/library/library.dialog.html delete mode 100644 src/app/dialogs/library/library.dialog.scss delete mode 100644 src/app/dialogs/library/library.dialog.spec.ts delete mode 100644 src/app/dialogs/library/library.dialog.ts create mode 100644 src/app/dialogs/node-version-upload/node-version-upload.dialog.html create mode 100644 src/app/dialogs/node-version-upload/node-version-upload.dialog.scss create mode 100644 src/app/dialogs/node-version-upload/node-version-upload.dialog.spec.ts rename src/app/{services/experimental-guard.service.spec.ts => dialogs/node-version-upload/node-version-upload.dialog.ts} (73%) delete mode 100644 src/app/directives/experimental.directive.ts create mode 100644 src/app/directives/lock-node.directive.spec.ts create mode 100644 src/app/directives/lock-node.directive.ts create mode 100644 src/app/extensions/evaluators/app.evaluators.spec.ts create mode 100644 src/app/extensions/evaluators/navigation.evaluators.spec.ts create mode 100644 src/app/services/app.service.spec.ts delete mode 100644 src/app/services/experimental-guard.service.ts create mode 100644 src/app/store/effects/search.effects.spec.ts create mode 100644 src/app/store/effects/upload.effects.spec.ts delete mode 100644 src/app/ui/overrides/adf-layout-header.theme.scss rename src/app/{directives/experimental.directive.spec.ts => utils/node.utils.ts} (62%) create mode 100644 src/assets/i18n/ar.json create mode 100644 src/assets/i18n/cs.json create mode 100644 src/assets/i18n/da.json create mode 100644 src/assets/i18n/fi.json create mode 100644 src/assets/i18n/pl.json create mode 100644 src/assets/i18n/sv.json create mode 100644 src/assets/images/baseline-lock-24px.svg delete mode 100644 src/assets/images/ic_lock_black_24dp_1x.png delete mode 100644 src/versions.json create mode 100755 start-sso.sh diff --git a/.gitignore b/.gitignore index a5dfadcc8d..082d3efc13 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json +!.vscode/*.code-snippets .history # misc diff --git a/.travis.yml b/.travis.yml index a9230e1b16..76225ff54b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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: diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000000..a398c3a8a4 --- /dev/null +++ b/.vscode/extensions.json @@ -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" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 5e62875a92..a143f058ac 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,5 +6,8 @@ "editor.formatOnSave": true, "[json]": { "editor.formatOnSave": false + }, + "markdownlint.config": { + "MD033": false } } diff --git a/.vscode/typescript.code-snippets b/.vscode/typescript.code-snippets new file mode 100644 index 0000000000..35f475e7dd --- /dev/null +++ b/.vscode/typescript.code-snippets @@ -0,0 +1,19 @@ +{ + "ext-evaluator": { + "description": "Generate a new evaluator.", + "scope": "typescript", + "prefix": "ext-evaluator", + "body": [ + "/**", + " * Checks if ${2:}.", + " * JSON ref: `app.$1`", + " */", + "export function ${1:name}(", + "\tcontext: AppRuleContext,", + "\t...args: RuleParameter[]", + "): boolean {", + "\treturn ${3:true};${0}", + "}" + ] + } +} diff --git a/Dockerfile b/Dockerfile index bf3087e396..c286db5f2e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 " -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 + +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 -ENTRYPOINT [ "/docker-entrypoint.sh" ] +EXPOSE 8080 +USER ${USERNAME} +ENTRYPOINT [ "/entrypoint.sh" ] diff --git a/README.md b/README.md index 25fbabd77c..4b212a49fc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -

Alfresco - make business flow

- +

Alfresco - make business flow

+ # Alfresco Content Application Testing Supported By
@@ -7,74 +7,97 @@ Testing Supported By
## 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). +- [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 diff --git a/angular.json b/angular.json index 2961f4555b..a2dafd68db 100644 --- a/angular.json +++ b/angular.json @@ -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", diff --git a/build-tomcat-e2e.sh b/build-tomcat-e2e.sh index 10ac86f0f0..72d2f9d753 100755 --- a/build-tomcat-e2e.sh +++ b/build-tomcat-e2e.sh @@ -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) diff --git a/cspell.json b/cspell.json index b63c3393aa..615efac647 100644 --- a/cspell.json +++ b/cspell.json @@ -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"] } diff --git a/docker-compose-keycloak.yml b/docker-compose-keycloak.yml new file mode 100644 index 0000000000..1022769be5 --- /dev/null +++ b/docker-compose-keycloak.yml @@ -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: diff --git a/docker-compose.yml b/docker-compose.yml index e484546775..a513d6a427 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -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: diff --git a/docker-compose/README.md b/docker-compose/README.md deleted file mode 100644 index 7cf4122e28..0000000000 --- a/docker-compose/README.md +++ /dev/null @@ -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 -``` diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml deleted file mode 100644 index b2813417cf..0000000000 --- a/docker-compose/docker-compose.yml +++ /dev/null @@ -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: diff --git a/docker-compose/nginx.conf b/docker-compose/nginx.conf deleted file mode 100644 index 816f208655..0000000000 --- a/docker-compose/nginx.conf +++ /dev/null @@ -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; - } -} diff --git a/docker/auth/alfresco-realm.json b/docker/auth/alfresco-realm.json new file mode 100644 index 0000000000..ca02bd1256 --- /dev/null +++ b/docker/auth/alfresco-realm.json @@ -0,0 +1,1673 @@ +{ + "id": "alfresco", + "realm": "alfresco", + "notBefore": 0, + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "offlineSessionIdleTimeout": 2592000, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "enabled": true, + "sslRequired": "none", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "39654467-e529-418e-bd27-354a0414fb52", + "name": "admin", + "scopeParamRequired": false, + "composite": false, + "clientRole": false, + "containerId": "alfresco" + }, + { + "id": "5b481c9b-38fe-474a-a047-50c3935262cb", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "scopeParamRequired": false, + "composite": false, + "clientRole": false, + "containerId": "alfresco" + }, + { + "id": "86db4867-8c3c-4cdf-8950-e18790f5bf6a", + "name": "offline_access", + "description": "${role_offline-access}", + "scopeParamRequired": true, + "composite": false, + "clientRole": false, + "containerId": "alfresco" + } + ], + "client": { + "realm-management": [ + { + "id": "a637f20f-fd3e-4db6-9d2a-c91acb1e14e8", + "name": "create-client", + "description": "${role_create-client}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "4232f8bf-dab4-4b4a-8ccf-28b8984f8ae7", + "name": "realm-admin", + "description": "${role_realm-admin}", + "scopeParamRequired": false, + "composite": true, + "composites": { + "client": { + "realm-management": [ + "create-client", + "view-authorization", + "manage-events", + "query-users", + "manage-authorization", + "view-realm", + "view-clients", + "query-clients", + "query-groups", + "impersonation", + "manage-users", + "manage-clients", + "manage-identity-providers", + "view-users", + "query-realms", + "view-identity-providers", + "view-events", + "manage-realm" + ] + } + }, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "ae0da5c2-643c-480e-8900-59bdca3581b3", + "name": "view-authorization", + "description": "${role_view-authorization}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "8a69ec22-4fe9-43e0-b4f0-16b632c2d324", + "name": "manage-events", + "description": "${role_manage-events}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "1c2c870c-5428-4144-ab12-c7304d1a7d2d", + "name": "query-users", + "description": "${role_query-users}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "9884df61-b63f-4f8b-8fba-650db69c8784", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "003ae8b9-e32a-4c0b-b319-d2a985249348", + "name": "view-realm", + "description": "${role_view-realm}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "d0d2eaa3-e737-4a7e-990d-4c6efa323cc3", + "name": "view-clients", + "description": "${role_view-clients}", + "scopeParamRequired": false, + "composite": true, + "composites": { + "client": { + "realm-management": ["query-clients"] + } + }, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "d9f0638c-e045-4d92-b4ff-e0c71f68f4ba", + "name": "query-clients", + "description": "${role_query-clients}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "02d5937c-929b-4928-8a55-b0de4c9b4924", + "name": "query-groups", + "description": "${role_query-groups}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "c74d9c9b-65e4-4847-a47a-3edbb2fce0fb", + "name": "impersonation", + "description": "${role_impersonation}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "e681501e-a8da-4653-861c-c37e2e1f8609", + "name": "manage-users", + "description": "${role_manage-users}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "067b5e3c-9918-4713-85ca-749c6aae13e1", + "name": "manage-clients", + "description": "${role_manage-clients}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "5b395e85-f5fa-4af9-b573-497cc9b1e694", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "b4ec253f-4d52-425e-b091-ed51aac7bd4c", + "name": "view-users", + "description": "${role_view-users}", + "scopeParamRequired": false, + "composite": true, + "composites": { + "client": { + "realm-management": ["query-groups", "query-users"] + } + }, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "574e930a-07d5-446f-9628-3d7568eb483a", + "name": "query-realms", + "description": "${role_query-realms}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "0cb1c9c8-55ce-4f22-b6d5-b6882c8b74fd", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "5d07f2b1-9f28-4e8b-8f91-7d68699d327c", + "name": "view-events", + "description": "${role_view-events}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + }, + { + "id": "53ccf3c9-4391-4d43-9d9e-6e644b989e9f", + "name": "manage-realm", + "description": "${role_manage-realm}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "c1f65e94-ed07-4bba-bafd-413db402a5f2" + } + ], + "security-admin-console": [], + "alfresco": [], + "admin-cli": [], + "broker": [ + { + "id": "560b729f-ebc7-4ce6-967b-045611d35cde", + "name": "read-token", + "description": "${role_read-token}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "887e537f-4a97-4374-a5de-45ad37bfe2df" + } + ], + "account": [ + { + "id": "86de6e40-74c1-4aa6-9a8b-bff434fb9a18", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "140feb9e-fd73-4d02-97f6-928ed67020f1" + }, + { + "id": "6a95ddc1-2b12-4e59-8d14-01a98c0fad71", + "name": "manage-account", + "description": "${role_manage-account}", + "scopeParamRequired": false, + "composite": true, + "composites": { + "client": { + "account": ["manage-account-links"] + } + }, + "clientRole": true, + "containerId": "140feb9e-fd73-4d02-97f6-928ed67020f1" + }, + { + "id": "a8e8d710-1f71-4481-93a1-db030533b64a", + "name": "view-profile", + "description": "${role_view-profile}", + "scopeParamRequired": false, + "composite": false, + "clientRole": true, + "containerId": "140feb9e-fd73-4d02-97f6-928ed67020f1" + } + ] + } + }, + "groups": [ + { + "id": "21cd4641-e7cb-456f-846d-214589cef3da", + "name": "admin", + "path": "/admin", + "attributes": {}, + "realmRoles": [], + "clientRoles": {}, + "subGroups": [] + } + ], + "defaultRoles": ["offline_access", "uma_authorization"], + "requiredCredentials": ["password"], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA256", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpSupportedApplications": ["FreeOTP"], + "clients": [ + { + "id": "fca5da6d-fd90-4596-a754-346d872b779f", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "baseUrl": "/auth/admin/alfresco/console/index.html", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": ["/auth/admin/alfresco/console/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "50435a57-d933-4392-aa63-c7b93969cb77", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "9d065ef2-ac16-4314-bdce-6df1e32b45da", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "f21fa9c5-090a-4873-a059-5a714e186e08", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "1d28c5e3-d1ab-4563-838d-06c61e96fd3c", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "0fd5ed6e-65af-4661-9d40-09a0dc90d705", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "consentText": "${locale}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "47febcd5-e6e8-4c83-8ea0-551f66cbef51", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "fc891ffd-b5b7-4d56-b1cd-60ae25ec0040", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "be13165d-2792-43aa-abdb-2c6cdb627184", + "clientId": "alfresco", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": ["*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": true, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "202b6b67-dea4-440b-b250-867fa7eb7333", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "cdb53973-5bf0-4de4-945d-901de3205016", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "8dd3c664-426e-44e7-931f-5e0700ed9e7f", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "aa1a443c-4716-424b-b695-49961d9cf98a", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "b29201a7-e442-47f6-a589-1b6faaf27b20", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "292f1e75-3216-447d-886a-6ab91b0dee1d", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "887e537f-4a97-4374-a5de-45ad37bfe2df", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "865fd86a-4c5e-4900-80de-34f30feb55b8", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "80b5d7cc-1ec3-4d73-8344-d0479bb4178a", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "54578e9a-e782-4a83-8f24-13da2b2f598c", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "a8cd846c-f538-4001-ba5f-e37d77ff87cd", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "a259f058-dbda-473a-b96e-2998958f8510", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "c7aed2b8-6716-4770-a936-31d973bdc557", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "c1f65e94-ed07-4bba-bafd-413db402a5f2", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "b51a2178-2121-42c8-9ae1-7a6f356377c0", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "091f3317-7f74-417f-9854-1726ede0fba8", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "033aeb3f-f04f-460b-9eeb-fd9376b1f639", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "5e3d143c-1792-41c1-bf10-2ece9684a8fc", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "e0464a63-f5ac-4fb8-9cf5-dc671badf59e", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "b68aec8b-327d-4238-8021-cefda0f66690", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "140feb9e-fd73-4d02-97f6-928ed67020f1", + "clientId": "account", + "name": "${client_account}", + "baseUrl": "/auth/realms/alfresco/account", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "defaultRoles": ["view-profile", "manage-account"], + "redirectUris": ["/auth/realms/alfresco/account/*"], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "fbda389d-78dd-4566-8238-c49a8809a3ac", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "88b68fdb-7f1b-459b-9013-2c1dfcb4ab87", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "9d129b38-1b18-4c79-a987-088ec7460d8d", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "6ca7c6ca-4d2f-4fbe-8288-c65ec1f1a2ef", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "dcaaafc2-72d0-41b1-9df1-250aa82c3aa3", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "64a2de57-3811-415f-a6b9-b550c3dfd8b0", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + }, + { + "id": "b5947c98-5a51-47f4-b7c9-935c491d17e9", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "clientAuthenticatorType": "client-secret", + "secret": "**********", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "3a7400ad-d225-401f-bdb7-91d60db990f6", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${username}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + }, + { + "id": "e4353798-aaac-40fa-967d-64aea182dd69", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${email}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "8fe5f0fa-b9f3-41c4-9a52-b195582d9239", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${familyName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "44872cc3-57b5-41d3-aae1-825dd2c350c0", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": true, + "consentText": "${fullName}", + "config": { + "id.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "29d794ba-6708-49cd-8a83-c50d6fc0e293", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + }, + { + "id": "4c266a5c-cb5f-407a-876e-18f002b7792a", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": true, + "consentText": "${givenName}", + "config": { + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + } + ], + "useTemplateConfig": false, + "useTemplateScope": false, + "useTemplateMappers": false + } + ], + "browserSecurityHeaders": { + "xContentTypeOptions": "nosniff", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "xXSSProtection": "1; mode=block", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';" + }, + "smtpServer": {}, + "loginTheme": "keycloak", + "eventsEnabled": false, + "eventsListeners": ["jboss-logging"], + "enabledEventTypes": [], + "adminEventsEnabled": false, + "adminEventsDetailsEnabled": false, + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "20f304be-9abc-4fa2-801e-c02440148d1b", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": ["true"], + "client-uris-must-match": ["true"] + } + }, + { + "id": "dd0ae9d2-7af3-4d38-b8e7-d9c5825d3b1f", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "b3099bb7-0064-4315-85d9-cdbcc0bfef71", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "7f35ed4a-2140-478b-b2f8-46585315b71f", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "oidc-usermodel-property-mapper", + "saml-role-list-mapper", + "saml-user-property-mapper", + "oidc-address-mapper", + "oidc-full-name-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-attribute-mapper" + ], + "consent-required-for-all-mappers": ["true"] + } + }, + { + "id": "30ac8e1b-b8e4-4877-aeab-42af7c2af5ff", + "name": "Allowed Client Templates", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "db5b54f2-258b-40f9-92f9-ef83a887d1fa", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "saml-user-attribute-mapper", + "oidc-usermodel-attribute-mapper", + "oidc-usermodel-property-mapper", + "saml-role-list-mapper", + "oidc-address-mapper", + "saml-user-property-mapper", + "oidc-full-name-mapper", + "oidc-sha256-pairwise-sub-mapper" + ], + "consent-required-for-all-mappers": ["true"] + } + }, + { + "id": "cd68d51f-9c85-4560-b1d6-9379bf3fce54", + "name": "Allowed Client Templates", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": {} + }, + { + "id": "cd3bfc37-cc55-40dc-8d83-98b76ad5a521", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": ["200"] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "14b13815-a8b1-412c-a98d-0da235e8c8f9", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": ["100"] + } + }, + { + "id": "306d8c4c-9ad1-444e-af1a-d6c67dffc5b7", + "name": "hmac-generated", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": ["100"] + } + }, + { + "id": "bff7cf8c-001f-4cfb-8d47-9a8bd5bc48d3", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": ["100"] + } + } + ] + }, + "internationalizationEnabled": true, + "supportedLocales": [ + "de", + "no", + "ru", + "sv", + "pt-BR", + "lt", + "en", + "it", + "fr", + "zh-CN", + "es", + "ja", + "ca", + "nl" + ], + "defaultLocale": "en", + "authenticationFlows": [ + { + "id": "ac4ffcd4-6547-4e1c-90ac-aa56304011fb", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "idp-email-verification", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "affb11d0-0542-4824-a433-a41e90295ec1", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "19c7907b-c38a-4cbf-b106-f42ae613fce7", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-spnego", + "requirement": "DISABLED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "identity-provider-redirector", + "requirement": "ALTERNATIVE", + "priority": 25, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "forms", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "5d678091-c1f9-4100-866f-fe35b032ae9d", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "requirement": "ALTERNATIVE", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "client-jwt", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "d41512a5-3b62-477c-9590-badbe9f8044d", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-password", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "direct-grant-validate-otp", + "requirement": "OPTIONAL", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "34c91e7e-dc6c-495a-889f-f033c9311911", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "d28bb33e-87a2-4712-a62c-01015ddfdf57", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "requirement": "ALTERNATIVE", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "requirement": "ALTERNATIVE", + "priority": 30, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "e65923ea-0c5b-43e3-9ebb-648391445207", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "auth-otp-form", + "requirement": "OPTIONAL", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "2d8d3a79-2e44-4d52-9aa2-919a400e0ab0", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "requirement": "REQUIRED", + "priority": 10, + "flowAlias": "registration form", + "userSetupAllowed": false, + "autheticatorFlow": true + } + ] + }, + { + "id": "5043cb5e-d76e-4a57-a0db-98366acb6bf7", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-profile-action", + "requirement": "REQUIRED", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-password-action", + "requirement": "REQUIRED", + "priority": 50, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "registration-recaptcha-action", + "requirement": "DISABLED", + "priority": 60, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "79f99e59-6a78-4262-a86a-231e0c69d4bd", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-credential-email", + "requirement": "REQUIRED", + "priority": 20, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-password", + "requirement": "REQUIRED", + "priority": 30, + "userSetupAllowed": false, + "autheticatorFlow": false + }, + { + "authenticator": "reset-otp", + "requirement": "OPTIONAL", + "priority": 40, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + }, + { + "id": "62e8ccd7-e995-4226-bee4-4ef9f1d6edc1", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "requirement": "REQUIRED", + "priority": 10, + "userSetupAllowed": false, + "autheticatorFlow": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "d1eae692-c7d2-4d52-ac4d-7b1231ce0a22", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "c6f89a26-2c86-4b6b-aee9-a483370fa20a", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "config": {} + }, + { + "alias": "terms_and_conditions", + "name": "Terms and Conditions", + "providerId": "terms_and_conditions", + "enabled": false, + "defaultAction": false, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "attributes": { + "_browser_header.xXSSProtection": "1; mode=block", + "_browser_header.xFrameOptions": "SAMEORIGIN", + "permanentLockout": "false", + "quickLoginCheckMilliSeconds": "1000", + "_browser_header.xRobotsTag": "none", + "maxFailureWaitSeconds": "900", + "minimumQuickLoginWaitSeconds": "60", + "failureFactor": "30", + "actionTokenGeneratedByUserLifespan": "300", + "maxDeltaTimeSeconds": "43200", + "_browser_header.xContentTypeOptions": "nosniff", + "actionTokenGeneratedByAdminLifespan": "43200", + "bruteForceProtected": "false", + "_browser_header.contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "waitIncrementSeconds": "60" + }, + "users": [ + { + "id": "9c978d30-c9ad-4dcb-b61c-840fe56f72f2", + "createdTimestamp": 1533234734911, + "username": "admin", + "enabled": true, + "totp": false, + "emailVerified": true, + "firstName": "admin", + "lastName": "admin", + "email": "admin.adf@alfresco.com", + "credentials": [ + { + "type": "password", + "value": "admin" + } + ], + "disableableCredentialTypes": ["password"], + "requiredActions": [], + "realmRoles": ["uma_authorization", "user", "offline_access"], + "clientRoles": { + "realm-management": [ + "view-clients", + "manage-users", + "manage-clients", + "view-users", + "manage-realm", + "view-realm" + ], + "account": ["manage-account", "view-profile"] + }, + "groups": ["/admin"] + } + ], + "keycloakVersion": "4.8.3.Final" +} diff --git a/docker-entrypoint.sh b/docker/entrypoint.sh similarity index 94% rename from docker-entrypoint.sh rename to docker/entrypoint.sh index 1ce3ab2a3d..1f7d7ee24a 100644 --- a/docker-entrypoint.sh +++ b/docker/entrypoint.sh @@ -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 diff --git a/docker/nginx.conf b/docker/nginx.conf new file mode 100644 index 0000000000..09126ac507 --- /dev/null +++ b/docker/nginx.conf @@ -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; + } + } +} diff --git a/docker/proxy/nginx.conf b/docker/proxy/nginx.conf new file mode 100644 index 0000000000..0eac5ac244 --- /dev/null +++ b/docker/proxy/nginx.conf @@ -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; + } +} diff --git a/docs/README.md b/docs/README.md index 1dc9b6cea6..82495c962d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,9 +1,14 @@ +--- +Title: Alfresco Content Application +Github only: true +--- + # Alfresco Content Application 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! diff --git a/docs/abn-tree.yml b/docs/abn-tree.yml new file mode 100644 index 0000000000..c05b84b58e --- /dev/null +++ b/docs/abn-tree.yml @@ -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' diff --git a/docs/extending/README.md b/docs/extending/README.md index 5ed182648e..20c56a4a42 100644 --- a/docs/extending/README.md +++ b/docs/extending/README.md @@ -1,4 +1,6 @@ --- +Title: Extending +Github only: true --- # Extending diff --git a/docs/extending/actions.md b/docs/extending/actions.md index 4519889bdb..a7b8b9cc7c 100644 --- a/docs/extending/actions.md +++ b/docs/extending/actions.md @@ -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. | diff --git a/docs/extending/application-actions.md b/docs/extending/application-actions.md index 3210da661c..368e09826b 100644 --- a/docs/extending/application-actions.md +++ b/docs/extending/application-actions.md @@ -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. -

-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. -

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 | diff --git a/docs/extending/application-features.md b/docs/extending/application-features.md index cecaac05f1..6b318815db 100644 --- a/docs/extending/application-features.md +++ b/docs/extending/application-features.md @@ -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. -

-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. -

+**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. -

-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. -

### 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. -

-In order to modify or disable existing entries, you need to know the id of the target element, along with its parents ids. -

+**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. - + +- 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. +{ + "$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`: ] ... -``` -

-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. -

diff --git a/docs/extending/components.md b/docs/extending/components.md index e978a69d9c..1533f96518 100644 --- a/docs/extending/components.md +++ b/docs/extending/components.md @@ -1,4 +1,5 @@ --- +Title: Components --- # Components diff --git a/docs/extending/creating-custom-evaluators.md b/docs/extending/creating-custom-evaluators.md index 957dc54d47..b6d9c1f36a 100644 --- a/docs/extending/creating-custom-evaluators.md +++ b/docs/extending/creating-custom-evaluators.md @@ -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`. -

-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. -

diff --git a/docs/extending/extensibility-features.md b/docs/extending/extensibility-features.md index 00c323ca94..22193d2c0a 100644 --- a/docs/extending/extensibility-features.md +++ b/docs/extending/extensibility-features.md @@ -1,4 +1,5 @@ --- +Title: Extensibility features --- # Extensibility features diff --git a/docs/extending/extension-format.md b/docs/extending/extension-format.md index ca78663654..1259eb654e 100644 --- a/docs/extending/extension-format.md +++ b/docs/extending/extension-format.md @@ -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). -

-The Schema allows you to validate extension files, provides code completion and documentation hints. -

+**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. } ``` -

-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. -

## 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. -

-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. -

### 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`. -

-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. -

### 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. -

-If array contains two objects with the same `id` property, the objects will be merged rather than appended. -

+**Tip:** If the array contains two objects with the same `id` property, the objects will be merged rather than appended. Before: Plugin 1 diff --git a/docs/extending/icons.md b/docs/extending/icons.md index 9903edb710..5bacc26a44 100644 --- a/docs/extending/icons.md +++ b/docs/extending/icons.md @@ -1,3 +1,7 @@ +--- +Title: Custom Icons +--- + # Custom Icons You can register and use custom `.svg` icons with toolbars, context menus, etc. diff --git a/docs/extending/redistributable-libraries.md b/docs/extending/redistributable-libraries.md index af848c211d..d7502dccd6 100644 --- a/docs/extending/redistributable-libraries.md +++ b/docs/extending/redistributable-libraries.md @@ -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. -

-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. -

## Publishing library to NPM @@ -155,9 +154,7 @@ npm install my-extension This installs the library and all its dependencies. -

-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. -

+**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. -

-Depending on the application setup, you may need enabling external plugins via the `Settings` dialog available for `admin` users (clicking the application profile button). -

+**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). diff --git a/docs/extending/registration.md b/docs/extending/registration.md index 285ffa419b..cf2500b1db 100644 --- a/docs/extending/registration.md +++ b/docs/extending/registration.md @@ -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. - -

-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. -

The Registration API is not limited to the custom content only. You can replace any existing entries by replacing the values from your module. diff --git a/docs/extending/routes.md b/docs/extending/routes.md index d72068ef43..5ba8af0db2 100644 --- a/docs/extending/routes.md +++ b/docs/extending/routes.md @@ -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. -

-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. -

You can define the full route schema like in the next example: diff --git a/docs/extending/rules.md b/docs/extending/rules.md index fef4e91eba..b8ce11fcac 100644 --- a/docs/extending/rules.md +++ b/docs/extending/rules.md @@ -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: } ``` -

-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`. -

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`. -

-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`. -

- -| 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**. | - -

-See [Registration](/extending/registration) section for more details + +| 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**. | + +**Tip:** See the [Registration](/extending/registration) section for more details on how to register your own entries to be re-used at runtime. -

### Example diff --git a/docs/extending/tutorials.md b/docs/extending/tutorials.md index 7f1d7be4e3..49c0d6bbca 100644 --- a/docs/extending/tutorials.md +++ b/docs/extending/tutorials.md @@ -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: diff --git a/docs/features/README.md b/docs/features/README.md index 1f4a0bfc51..60ced23752 100644 --- a/docs/features/README.md +++ b/docs/features/README.md @@ -1,4 +1,6 @@ --- +Title: Application features +Github only: true --- # Application features diff --git a/docs/features/document-list-layout.md b/docs/features/document-list-layout.md index 1d1726cdb7..f13310d6a8 100644 --- a/docs/features/document-list-layout.md +++ b/docs/features/document-list-layout.md @@ -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//`) 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//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//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. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ActionFileFolder
View - Opens the selected file using the Preview component, - where the file cannot be displayed natively in a browser a PDF rendition is obtained from the repository. - Not applicable
DownloadDownloads 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.
EditNot applicableThe folder name and description can be edited in a dialog.
Favorite - 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. -
Copy - Files and folders can be copied to another location in the content repository using the - content-node-selector component; - once 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; - once the move action has completed the user is notified and can undo the action (which moves the items back to the original location). -
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. -
Delete - 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). -
Manage Versions - 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. - 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
+| 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 diff --git a/docs/features/file-viewer.md b/docs/features/file-viewer.md index a0dea420c5..2f62e76fbc 100644 --- a/docs/features/file-viewer.md +++ b/docs/features/file-viewer.md @@ -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. diff --git a/docs/features/header.md b/docs/features/header.md index 8f2953b05a..7696b4a76a 100644 --- a/docs/features/header.md +++ b/docs/features/header.md @@ -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) diff --git a/docs/features/info-drawer.md b/docs/features/info-drawer.md index 62aa2162b6..11d34bd9d7 100644 --- a/docs/features/info-drawer.md +++ b/docs/features/info-drawer.md @@ -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. diff --git a/docs/features/search-results.md b/docs/features/search-results.md index 6c5aafe0b5..1d51d37861 100644 --- a/docs/features/search-results.md +++ b/docs/features/search-results.md @@ -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. diff --git a/docs/features/side-navigation.md b/docs/features/side-navigation.md index 4d5e4c14d8..aa54343846 100644 --- a/docs/features/side-navigation.md +++ b/docs/features/side-navigation.md @@ -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. diff --git a/docs/features/user-interface-layout.md b/docs/features/user-interface-layout.md index aa8f6b5b54..962785121c 100644 --- a/docs/features/user-interface-layout.md +++ b/docs/features/user-interface-layout.md @@ -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) diff --git a/docs/features/version-manager.md b/docs/features/version-manager.md index 22dff20ec3..b25144bf5e 100644 --- a/docs/features/version-manager.md +++ b/docs/features/version-manager.md @@ -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. diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index e3ed3c9b62..38a7872ca3 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -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) \ No newline at end of file +- [Docker](/getting-started/docker) diff --git a/docs/getting-started/building-from-source.md b/docs/getting-started/building-from-source.md index 084b279229..418522cefd 100644 --- a/docs/getting-started/building-from-source.md +++ b/docs/getting-started/building-from-source.md @@ -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. -

-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. -

## Running unit tests -Run `npm test` to execute the unit tests via [Karma](https://karma-runner.github.io). \ No newline at end of file +Run `npm test` to execute the unit tests via [Karma](https://karma-runner.github.io). diff --git a/docs/getting-started/configuration.md b/docs/getting-started/configuration.md index 98e331c988..75204baa05 100644 --- a/docs/getting-started/configuration.md +++ b/docs/getting-started/configuration.md @@ -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, - ... -} -``` - -#### 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}", - ... + "baseShareUrl": "{protocol}//{hostname}{:port}/#/preview/s" } ``` -

-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}". -

- - ## 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: } ``` -

-You can get more details on the supported rules in the following article: Upload Service. -

+**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. -

-Please refer to the AppConfigService documentation to get more details on Application Configuration features and API's available. -

+**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. diff --git a/docs/getting-started/cors.md b/docs/getting-started/cors.md index 6396ce7f2f..cddddfd6a9 100644 --- a/docs/getting-started/cors.md +++ b/docs/getting-started/cors.md @@ -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 diff --git a/docs/getting-started/docker.md b/docs/getting-started/docker.md index 8b3a0f6ed4..67c932663b 100644 --- a/docs/getting-started/docker.md +++ b/docs/getting-started/docker.md @@ -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 - -

-With this mode, you do not need building application from source code or installing dependencies. -

- -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. diff --git a/docs/getting-started/internationalization.md b/docs/getting-started/internationalization.md index b929d4b9dd..de9ebbaf52 100644 --- a/docs/getting-started/internationalization.md +++ b/docs/getting-started/internationalization.md @@ -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 diff --git a/docs/getting-started/navigation.md b/docs/getting-started/navigation.md index b6275c89d5..c684b366bc 100644 --- a/docs/getting-started/navigation.md +++ b/docs/getting-started/navigation.md @@ -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. -

- Changing ` "route": { "url": "/..." } ` value will affect the navigation since these are mapped to application routing system. -

+**Caution:** Changing ` "route": { "url": "/..." } ` value will affect the navigation since these are mapped to application routing system. ### Custom text (i18n) diff --git a/docs/getting-started/prerequisites.md b/docs/getting-started/prerequisites.md index bdb5dc7a97..5cb03903d0 100644 --- a/docs/getting-started/prerequisites.md +++ b/docs/getting-started/prerequisites.md @@ -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) -

-You also need node.js (LTS) installed to build it locally from source code. -

+**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. \ No newline at end of file diff --git a/docs/getting-started/sso.md b/docs/getting-started/sso.md new file mode 100644 index 0000000000..14029f60f3 --- /dev/null +++ b/docs/getting-started/sso.md @@ -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. diff --git a/docs/help.md b/docs/help.md index 926f1aeba0..5458d282a8 100644 --- a/docs/help.md +++ b/docs/help.md @@ -1,5 +1,5 @@ --- -title: Get Help +Title: Get Help --- # Where to get help diff --git a/docs/images/aca-sso-settings.png b/docs/images/aca-sso-settings.png new file mode 100644 index 0000000000000000000000000000000000000000..7fa3f3e54aac0fa3dd11273a55a5fb7c385230c8 GIT binary patch literal 106750 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 b!{0QvFBjexS-@Wh{+<8X{3rZrmplI-ZI&qQ literal 0 HcmV?d00001 diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md index 1758fcc80c..ba178af6da 100644 --- a/docs/tutorials/README.md +++ b/docs/tutorials/README.md @@ -1,4 +1,6 @@ --- +Title: Tutorials +Github only: true --- # Tutorials diff --git a/docs/tutorials/custom-route-with-parameters.md b/docs/tutorials/custom-route-with-parameters.md index cba3b730d7..eadb8ca9c2 100644 --- a/docs/tutorials/custom-route-with-parameters.md +++ b/docs/tutorials/custom-route-with-parameters.md @@ -1,4 +1,5 @@ --- +Title: Custom route with parameters --- # Custom route with parameters diff --git a/docs/tutorials/dialog-actions.md b/docs/tutorials/dialog-actions.md index 0773afe4b7..6d82285874 100644 --- a/docs/tutorials/dialog-actions.md +++ b/docs/tutorials/dialog-actions.md @@ -1,4 +1,5 @@ --- +Title: Dialog actions --- # Dialog actions diff --git a/docs/tutorials/introduction-to-extending.md b/docs/tutorials/introduction-to-extending.md index fb850d25ec..47daaa33f7 100644 --- a/docs/tutorials/introduction-to-extending.md +++ b/docs/tutorials/introduction-to-extending.md @@ -1,6 +1,7 @@ --- +Title: Introduction to extending ACA --- # Introduction to extending the Alfresco Content Application -An introductory tutorial will appear here shortly. \ No newline at end of file +Place holder for a future tutorial. diff --git a/e2e/components/breadcrumb/breadcrumb.ts b/e2e/components/breadcrumb/breadcrumb.ts index 662e72743f..c322999fa7 100755 --- a/e2e/components/breadcrumb/breadcrumb.ts +++ b/e2e/components/breadcrumb/breadcrumb.ts @@ -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 diff --git a/e2e/components/component.ts b/e2e/components/component.ts index a2fc3cf698..a4153987c9 100755 --- a/e2e/components/component.ts +++ b/e2e/components/component.ts @@ -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 diff --git a/e2e/components/components.ts b/e2e/components/components.ts index f8d1b44b51..a1440fa843 100755 --- a/e2e/components/components.ts +++ b/e2e/components/components.ts @@ -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 diff --git a/e2e/components/data-table/data-table.ts b/e2e/components/data-table/data-table.ts index 645e7273b9..5f0b9093db 100755 --- a/e2e/components/data-table/data-table.ts +++ b/e2e/components/data-table/data-table.ts @@ -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; + }, {}); + } + } diff --git a/e2e/components/datetime-picker/datetime-picker.ts b/e2e/components/datetime-picker/datetime-picker.ts index 9b746a520e..b4475a43c5 100755 --- a/e2e/components/datetime-picker/datetime-picker.ts +++ b/e2e/components/datetime-picker/datetime-picker.ts @@ -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 diff --git a/e2e/components/dialog/confirm-dialog.ts b/e2e/components/dialog/confirm-dialog.ts index 5f2e446166..f262658906 100755 --- a/e2e/components/dialog/confirm-dialog.ts +++ b/e2e/components/dialog/confirm-dialog.ts @@ -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'); + } + } diff --git a/e2e/components/dialog/copy-move-dialog.ts b/e2e/components/dialog/copy-move-dialog.ts index aa2e5211d8..7cafe2b379 100755 --- a/e2e/components/dialog/copy-move-dialog.ts +++ b/e2e/components/dialog/copy-move-dialog.ts @@ -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(); diff --git a/e2e/components/dialog/create-edit-folder-dialog.ts b/e2e/components/dialog/create-edit-folder-dialog.ts index d3d4cd5ec2..f1ef82c5c0 100755 --- a/e2e/components/dialog/create-edit-folder-dialog.ts +++ b/e2e/components/dialog/create-edit-folder-dialog.ts @@ -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 . */ -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(); } + } diff --git a/e2e/components/dialog/create-library-dialog.ts b/e2e/components/dialog/create-library-dialog.ts index 074d5beeba..cfe8bca507 100755 --- a/e2e/components/dialog/create-library-dialog.ts +++ b/e2e/components/dialog/create-library-dialog.ts @@ -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]', diff --git a/e2e/components/dialog/manage-versions-dialog.ts b/e2e/components/dialog/manage-versions-dialog.ts index 94f00315af..d367bd8e0e 100755 --- a/e2e/components/dialog/manage-versions-dialog.ts +++ b/e2e/components/dialog/manage-versions-dialog.ts @@ -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 diff --git a/e2e/components/dialog/share-dialog.ts b/e2e/components/dialog/share-dialog.ts index 827fae15a4..51518a70c3 100755 --- a/e2e/components/dialog/share-dialog.ts +++ b/e2e/components/dialog/share-dialog.ts @@ -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(); diff --git a/e2e/components/dialog/upload-new-version-dialog.ts b/e2e/components/dialog/upload-new-version-dialog.ts new file mode 100755 index 0000000000..f3654bfd07 --- /dev/null +++ b/e2e/components/dialog/upload-new-version-dialog.ts @@ -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 . + */ + +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); + } + +} diff --git a/e2e/components/header/header.ts b/e2e/components/header/header.ts index b14777c062..eac79c00c6 100755 --- a/e2e/components/header/header.ts +++ b/e2e/components/header/header.ts @@ -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 . */ -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') + } + } + } diff --git a/e2e/components/header/user-info.ts b/e2e/components/header/user-info.ts index 805a257d04..71c77b548c 100755 --- a/e2e/components/header/user-info.ts +++ b/e2e/components/header/user-info.ts @@ -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(); diff --git a/e2e/components/info-drawer/info-drawer.ts b/e2e/components/info-drawer/info-drawer.ts index ba4a7a5fc4..b366ff4359 100755 --- a/e2e/components/info-drawer/info-drawer.ts +++ b/e2e/components/info-drawer/info-drawer.ts @@ -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 . */ -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 { + await this.getTabByTitle('Comments').click(); + await this.waitForCommentsTabContainer(); + await browser.wait(EC.visibilityOf(this.addCommentButton), BROWSER_WAIT_TIMEOUT); + } catch (error) { + console.error('--- catch error on clickCommentsTab ---'); + throw error; + } + } + + async clickAboutTab() { try { - const disabled = await this.getButton(button).getAttribute('disabled'); - return disabled; + return await this.getTabByTitle('About').click(); } catch (error) { - console.log('----- isButtonDisabled 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 isNameEnabled() { + return await this.isInputEnabled('Name'); } async getName() { return await this.getValueOfField('Name'); } - async getVisibility() { - return await this.getValueOfField('Visibility'); - } - - async getLibraryId() { - return await this.getValueOfField('Library ID'); + async enterName(name: string) { + return await this.enterTextInInput('Name', name); } - async getDescription() { - return await this.getValueOfField('Description'); - } - async isNameEnabled() { - return await this.isInputEnabled('Name'); - } - - async isLibraryIdEnabled() { - return await this.isInputEnabled('Library ID'); + async isDescriptionDisplayed() { + return await this.isFieldDisplayed('Description'); } async isDescriptionEnabled() { return await this.isInputEnabled('Description'); } - async enterName(name: string) { - return await this.enterTextInInput('Name', name); - } - - async typeName(name: string) { - return await this.typeTextInInput('Name', name); + 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'); + } } diff --git a/e2e/components/login/login.ts b/e2e/components/login/login.ts index 0001e10c62..9d33decb2a 100755 --- a/e2e/components/login/login.ts +++ b/e2e/components/login/login.ts @@ -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()); + } + } diff --git a/e2e/components/menu/menu.ts b/e2e/components/menu/menu.ts index 4edfa7633b..07b9ae09c4 100755 --- a/e2e/components/menu/menu.ts +++ b/e2e/components/menu/menu.ts @@ -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(); + } + } diff --git a/e2e/components/metadata-card/metadata-card.ts b/e2e/components/metadata-card/metadata-card.ts index 7c62895785..12b3d86096 100644 --- a/e2e/components/metadata-card/metadata-card.ts +++ b/e2e/components/metadata-card/metadata-card.ts @@ -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 diff --git a/e2e/components/pagination/pagination.ts b/e2e/components/pagination/pagination.ts index 04326ace84..b5b5d5aea7 100755 --- a/e2e/components/pagination/pagination.ts +++ b/e2e/components/pagination/pagination.ts @@ -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(); + } } diff --git a/e2e/components/search/search-input.ts b/e2e/components/search/search-input.ts index 5bf99c1650..6246561ca3 100755 --- a/e2e/components/search/search-input.ts +++ b/e2e/components/search/search-input.ts @@ -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 . */ -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(); + } } diff --git a/e2e/components/sidenav/sidenav.ts b/e2e/components/sidenav/sidenav.ts index 145c772e4b..c138c7e3d8 100755 --- a/e2e/components/sidenav/sidenav.ts +++ b/e2e/components/sidenav/sidenav.ts @@ -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 . */ -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); } } diff --git a/e2e/components/toolbar/toolbar.ts b/e2e/components/toolbar/toolbar.ts index d337b8f6cb..baf0108ff4 100755 --- a/e2e/components/toolbar/toolbar.ts +++ b/e2e/components/toolbar/toolbar.ts @@ -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 . */ -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() { - const btn = this.shareButton; - await btn.click(); + + async isSharedLinkSettingsPresent() { + return await browser.isElementPresent(this.shareEditButton); } - async isShareButtonPresent() { + async isSharePresent() { return await browser.isElementPresent(this.shareButton); } - async clickShareEditButton() { + 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 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(); + } + } diff --git a/e2e/components/viewer/viewer.ts b/e2e/components/viewer/viewer.ts index d1c48d028c..60cb6709ac 100755 --- a/e2e/components/viewer/viewer.ts +++ b/e2e/components/viewer/viewer.ts @@ -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() { diff --git a/e2e/configs.ts b/e2e/configs.ts index 18f23a8859..c663f1c017 100755 --- a/e2e/configs.ts +++ b/e2e/configs.ts @@ -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' }; diff --git a/e2e/pages/browsing-page.ts b/e2e/pages/browsing-page.ts index 31b25dd903..f11b78f208 100755 --- a/e2e/pages/browsing-page.ts +++ b/e2e/pages/browsing-page.ts @@ -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 clickPersonalFiles() { + await this.sidenav.clickLink(SIDEBAR_LABELS.PERSONAL_FILES); + } + async clickPersonalFilesAndWait() { - await this.sidenav.navigateToLink(SIDEBAR_LABELS.PERSONAL_FILES); + await this.clickPersonalFiles(); await this.dataTable.waitForHeader(); } - async clickPersonalFiles() { - await this.sidenav.navigateToLink(SIDEBAR_LABELS.PERSONAL_FILES); - } + async clickFileLibraries() { + await this.sidenav.clickLink(SIDEBAR_LABELS.FILE_LIBRARIES); + } async clickFileLibrariesAndWait() { - await this.sidenav.expandFileLibraries(); - await this.sidenav.navigateToLink(SIDEBAR_LABELS.MY_LIBRARIES); + await this.clickFileLibraries(); await this.dataTable.waitForHeader(); } - async clickFileLibraries() { - await this.sidenav.expandFileLibraries(); - await this.sidenav.navigateToLink(SIDEBAR_LABELS.MY_LIBRARIES); - } async goToFavoriteLibraries() { - await this.sidenav.expandFileLibraries(); - await this.sidenav.navigateToLink(SIDEBAR_LABELS.FAVORITE_LIBRARIES); + 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 clickRecentFilesAndWait() { - await this.sidenav.navigateToLink(SIDEBAR_LABELS.RECENT_FILES); + async goToMyLibrariesAndWait() { + await this.goToMyLibraries(); await this.dataTable.waitForHeader(); } + async clickRecentFiles() { - await this.sidenav.navigateToLink(SIDEBAR_LABELS.RECENT_FILES); + await this.sidenav.clickLink(SIDEBAR_LABELS.RECENT_FILES); } - - async clickSharedFilesAndWait() { - await this.sidenav.navigateToLink(SIDEBAR_LABELS.SHARED_FILES); + async clickRecentFilesAndWait() { + await this.clickRecentFiles(); 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(); } } diff --git a/e2e/pages/login-page.ts b/e2e/pages/login-page.ts index 26d631776c..4bcc347506 100755 --- a/e2e/pages/login-page.ts +++ b/e2e/pages/login-page.ts @@ -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 diff --git a/e2e/pages/page.ts b/e2e/pages/page.ts index ac8c67d652..0d7a72cebd 100755 --- a/e2e/pages/page.ts +++ b/e2e/pages/page.ts @@ -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'); + } + } diff --git a/e2e/pages/pages.ts b/e2e/pages/pages.ts index cc8b384433..1a2bd70d37 100755 --- a/e2e/pages/pages.ts +++ b/e2e/pages/pages.ts @@ -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 diff --git a/e2e/pages/search-results-page.ts b/e2e/pages/search-results-page.ts index 76c0b3ee93..5ec2a4e10a 100755 --- a/e2e/pages/search-results-page.ts +++ b/e2e/pages/search-results-page.ts @@ -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 . */ -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(); + } } diff --git a/e2e/resources/extensibility-configs/context-submenus-ext.json b/e2e/resources/extensibility-configs/context-submenus-ext.json index cfb41c8e95..51c26e0c26 100644 --- a/e2e/resources/extensibility-configs/context-submenus-ext.json +++ b/e2e/resources/extensibility-configs/context-submenus-ext.json @@ -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 }, diff --git a/e2e/resources/extensibility-configs/document-presets-ext.json b/e2e/resources/extensibility-configs/document-presets-ext.json index 64dd837849..45f006c3d9 100644 --- a/e2e/resources/extensibility-configs/document-presets-ext.json +++ b/e2e/resources/extensibility-configs/document-presets-ext.json @@ -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 }, diff --git a/e2e/resources/extensibility-configs/extensions-default.json b/e2e/resources/extensibility-configs/extensions-default.json index d46e6fa117..348d85289a 100644 --- a/e2e/resources/extensibility-configs/extensions-default.json +++ b/e2e/resources/extensibility-configs/extensions-default.json @@ -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": [ diff --git a/e2e/resources/extensibility-configs/header-ext.json b/e2e/resources/extensibility-configs/header-ext.json index 5439bd575c..7d3f5086a5 100644 --- a/e2e/resources/extensibility-configs/header-ext.json +++ b/e2e/resources/extensibility-configs/header-ext.json @@ -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": [ diff --git a/e2e/resources/extensibility-configs/metadata-ext.json b/e2e/resources/extensibility-configs/metadata-ext.json index 01273636fe..a93b3d1569 100644 --- a/e2e/resources/extensibility-configs/metadata-ext.json +++ b/e2e/resources/extensibility-configs/metadata-ext.json @@ -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": [ diff --git a/e2e/resources/extensibility-configs/viewer-ext.json b/e2e/resources/extensibility-configs/viewer-ext.json index 74f0ce5299..352f137e21 100644 --- a/e2e/resources/extensibility-configs/viewer-ext.json +++ b/e2e/resources/extensibility-configs/viewer-ext.json @@ -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": [ diff --git a/e2e/resources/test-files/file2-docx.docx b/e2e/resources/test-files/file2-docx.docx new file mode 100644 index 0000000000000000000000000000000000000000..c0d0614a84fc9b0ab28ab8964f91a7c74181a5f2 GIT binary patch literal 11523 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 literal 0 HcmV?d00001 diff --git a/e2e/resources/test-files/file2-xlsx.xlsx b/e2e/resources/test-files/file2-xlsx.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..3039a7cdc8579121f821af3dbb78590f00ba19f6 GIT binary patch literal 97629 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 literal 0 HcmV?d00001 diff --git a/e2e/suites/actions/context-menu-multiple-selection.test.ts b/e2e/suites/actions/context-menu-multiple-selection.test.ts index 85a472b040..0283d3a9f8 100755 --- a/e2e/suites/actions/context-menu-multiple-selection.test.ts +++ b/e2e/suites/actions/context-menu-multiple-selection.test.ts @@ -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 . */ -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`); }); }); }); diff --git a/e2e/suites/actions/context-menu-single-selection.test.ts b/e2e/suites/actions/context-menu-single-selection.test.ts index 96cdfd9346..ed80b3d02b 100755 --- a/e2e/suites/actions/context-menu-single-selection.test.ts +++ b/e2e/suites/actions/context-menu-single-selection.test.ts @@ -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 . */ -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(); + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + 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 a member - [C290081]', 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.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 - 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.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.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 - 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.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 - 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.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}`); }); }); @@ -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}`); }); }); }); diff --git a/e2e/suites/actions/copy.test.ts b/e2e/suites/actions/copy.test.ts new file mode 100755 index 0000000000..4de50108ef --- /dev/null +++ b/e2e/suites/actions/copy.test.ts @@ -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 . + */ + +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`); + }); + }); + +}); diff --git a/e2e/suites/actions/create-folder.test.ts b/e2e/suites/actions/create-folder.test.ts index 76601f9eab..b423704256 100755 --- a/e2e/suites/actions/create-folder.test.ts +++ b/e2e/suites/actions/create-folder.test.ts @@ -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(''); }); diff --git a/e2e/suites/actions/create-library.test.ts b/e2e/suites/actions/create-library.test.ts index 1d1fabc1ce..6d8c8d3aca 100755 --- a/e2e/suites/actions/create-library.test.ts +++ b/e2e/suites/actions/create-library.test.ts @@ -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 @@ -85,6 +85,7 @@ describe('Create library', () => { it('Create Library dialog UI - [C280024]', async () => { await page.sidenav.openCreateLibraryDialog(); await createDialog.waitForDialogToOpen(); + expect(await createDialog.getTitle()).toMatch('Create Library'); expect(await createDialog.isNameDisplayed()).toBe(true, 'Name input is not displayed'); expect(await createDialog.isLibraryIdDisplayed()).toBe(true, 'Library ID input is not displayed'); @@ -103,10 +104,10 @@ describe('Create library', () => { await createDialog.enterName(site1Name); await createDialog.clickCreate(); await createDialog.waitForDialogToClose(); - const current = await page.breadcrumb.getCurrentItemName(); - expect(current).toEqual(site1Name, `Not navigated into ${site1Name}`); - await page.clickFileLibrariesAndWait(); - expect(await dataTable.getRowByName(site1Name).isPresent()).toBe(true, `${site1Name} not in the list`); + + expect(await page.breadcrumb.getCurrentItemName()).toEqual(site1Name, `Not navigated into ${site1Name}`); + await page.goToMyLibrariesAndWait(); + expect(await dataTable.isItemPresent(site1Name)).toBe(true, `${site1Name} not in the list`); expect(await apis.user.sites.getVisibility(site1Name)).toEqual(SITE_VISIBILITY.PUBLIC); }); @@ -117,10 +118,10 @@ describe('Create library', () => { await createDialog.selectModerated(); await createDialog.clickCreate(); await createDialog.waitForDialogToClose(); - const current = await page.breadcrumb.getCurrentItemName(); - expect(current).toEqual(site2Name, `Not navigated into ${site2Name}`); - await page.clickFileLibrariesAndWait(); - expect(await dataTable.getRowByName(site2Name).isPresent()).toBe(true, `${site2Name} not in the list`); + + expect(await page.breadcrumb.getCurrentItemName()).toEqual(site2Name, `Not navigated into ${site2Name}`); + await page.goToMyLibrariesAndWait(); + expect(await dataTable.isItemPresent(site2Name)).toBe(true, `${site2Name} not in the list`); expect(await apis.user.sites.getVisibility(site2Name)).toEqual(SITE_VISIBILITY.MODERATED); }); @@ -131,10 +132,10 @@ describe('Create library', () => { await createDialog.selectPrivate(); await createDialog.clickCreate(); await createDialog.waitForDialogToClose(); - const current = await page.breadcrumb.getCurrentItemName(); - expect(current).toEqual(site3Name, `Not navigated into ${site3Name}`); - await page.clickFileLibrariesAndWait(); - expect(await dataTable.getRowByName(site3Name).isPresent()).toBe(true, `${site3Name} not in the list`); + + expect(await page.breadcrumb.getCurrentItemName()).toEqual(site3Name, `Not navigated into ${site3Name}`); + await page.goToMyLibrariesAndWait(); + expect(await dataTable.isItemPresent(site3Name)).toBe(true, `${site3Name} not in the list`); expect(await apis.user.sites.getVisibility(site3Name)).toEqual(SITE_VISIBILITY.PRIVATE); }); @@ -147,10 +148,10 @@ describe('Create library', () => { await createDialog.selectPublic(); await createDialog.clickCreate(); await createDialog.waitForDialogToClose(); - const current = await page.breadcrumb.getCurrentItemName(); - expect(current).toEqual(site4.name, `Not navigated into ${site4.name}`); - await page.clickFileLibrariesAndWait(); - expect(await dataTable.getRowByName(site4.name).isPresent()).toBe(true, `${site4.name} not in the list`); + + expect(await page.breadcrumb.getCurrentItemName()).toEqual(site4.name, `Not navigated into ${site4.name}`); + await page.goToMyLibrariesAndWait(); + expect(await dataTable.isItemPresent(site4.name)).toBe(true, `${site4.name} not in the list`); expect(await apis.user.sites.getVisibility(site4.id)).toEqual(SITE_VISIBILITY.PUBLIC); expect(await apis.user.sites.getDescription(site4.id)).toEqual(site4.description); }); @@ -160,9 +161,9 @@ describe('Create library', () => { await createDialog.waitForDialogToOpen(); await createDialog.enterName(duplicateSite.name); await createDialog.enterLibraryId(duplicateSite.id); + expect(await createDialog.isCreateEnabled()).toBe(false, 'Create button not disabled'); - const err = await createDialog.getErrorMessage(); - expect(err).toEqual(`This Library ID isn't available. Try a different Library ID.`); + expect(await createDialog.getErrorMessage()).toEqual(`This Library ID isn't available. Try a different Library ID.`); }); it('Create library using the ID of a library from the Trashcan - [C280028]', async () => { @@ -171,8 +172,8 @@ describe('Create library', () => { await createDialog.enterName(siteInTrash.name); await createDialog.enterLibraryId(siteInTrash.id); await createDialog.clickCreate(); - const err = await createDialog.getErrorMessage(); - expect(err).toEqual(`This Library ID is already used. Check the trashcan.`); + + expect(await createDialog.getErrorMessage()).toEqual(`This Library ID is already used. Check the trashcan.`); }); it('Cancel button - [C280029]', async () => { @@ -181,6 +182,7 @@ describe('Create library', () => { await createDialog.enterName('test site'); await createDialog.enterDescription('test description'); await createDialog.clickCancel(); + expect(await createDialog.isDialogOpen()).not.toBe(true, 'dialog is not closed'); }); @@ -205,10 +207,10 @@ describe('Create library', () => { await createDialog.enterLibraryId(`${duplicateSite.id}-2`); await createDialog.clickCreate(); await createDialog.waitForDialogToClose(); - const current = await page.breadcrumb.getCurrentItemName(); - expect(current).toEqual(duplicateSite.name, `Not navigated into ${duplicateSite.name}`); - await page.clickFileLibrariesAndWait(); - expect(await dataTable.getRowByName(`${duplicateSite.name} (${duplicateSite.id}-2)`).isPresent()).toBe(true, `${duplicateSite.name} not in the list`); + + expect(await page.breadcrumb.getCurrentItemName()).toEqual(duplicateSite.name, `Not navigated into ${duplicateSite.name}`); + await page.goToMyLibrariesAndWait(); + expect(await dataTable.isItemPresent(`${duplicateSite.name} (${duplicateSite.id}-2)`)).toBe(true, `${duplicateSite.name} not in the list`); expect(await apis.user.sites.getTitle(`${duplicateSite.id}-2`)).toEqual(duplicateSite.name); }); diff --git a/e2e/suites/actions/delete-undo-delete.test.ts b/e2e/suites/actions/delete-undo-delete.test.ts index d82173311f..f478e5df5a 100755 --- a/e2e/suites/actions/delete-undo-delete.test.ts +++ b/e2e/suites/actions/delete-undo-delete.test.ts @@ -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,6 @@ * along with Alfresco. If not, see . */ -import { browser } from 'protractor'; import { LoginPage, BrowsingPage } from '../../pages/pages'; import { RepoClient } from '../../utilities/repo-client/repo-client'; import { Utils } from '../../utilities/utils'; @@ -50,196 +49,183 @@ describe('Delete and undo delete', () => { done(); }); - xit(''); - describe('on Personal Files', () => { - const file1 = `file1-${Utils.random()}.txt`; let file1Id; - const file2 = `file2-${Utils.random()}.txt`; let file2Id; + const file1 = `file1-${Utils.random()}.txt`; + const file2 = `file2-${Utils.random()}.txt`; const file3 = `file3-${Utils.random()}.txt`; - const file4 = `file4-${Utils.random()}.txt`; let file4Id; + const file4 = `file4-${Utils.random()}.txt`; + const file5 = `file5-${Utils.random()}.txt`; + const file6 = `file6-${Utils.random()}.txt`; + const file7 = `file7-${Utils.random()}.txt`; + const folder1 = `folder1-${Utils.random()}`; let folder1Id; const folder2 = `folder2-${Utils.random()}`; let folder2Id; const folder3 = `folder3-${Utils.random()}`; let folder3Id; + const folder4 = `folder4-${Utils.random()}`; let folder4Id; + const folder5 = `folder5-${Utils.random()}`; let folder5Id; + const folder6 = `folder6-${Utils.random()}`; let folder6Id; + + const file1InFolder = `file1InFolder-${Utils.random()}.txt`; + const file2InFolder = `file2InFolder-${Utils.random()}.txt`; const fileLocked1 = `fileLocked1-${Utils.random()}.txt`; let fileLocked1Id; const fileLocked2 = `fileLocked2-${Utils.random()}.txt`; let fileLocked2Id; + const fileLocked3 = `fileLocked3-${Utils.random()}.txt`; let fileLocked3Id; + const fileLocked4 = `fileLocked4-${Utils.random()}.txt`; let fileLocked4Id; - beforeAll(async (done) => { - 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; - await apis.user.nodes.createFile(file3, folder1Id); - file4Id = (await apis.user.nodes.createFile(file4, folder2Id)).entry.id; - await apis.user.nodes.lockFile(file4Id); + const parent = `parentPF-${Utils.random()}`; let parentId; - folder3Id = (await apis.user.nodes.createFolder(folder3)).entry.id; + beforeAll(async (done) => { + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + + await apis.user.nodes.createFile(file1, parentId); + await apis.user.nodes.createFile(file2, parentId); + await apis.user.nodes.createFile(file3, parentId); + await apis.user.nodes.createFile(file4, parentId); + await apis.user.nodes.createFile(file5, parentId); + await apis.user.nodes.createFile(file6, parentId); + await apis.user.nodes.createFile(file7, parentId); + + folder1Id = (await apis.user.nodes.createFolder(folder1, parentId)).entry.id; + folder2Id = (await apis.user.nodes.createFolder(folder2, parentId)).entry.id; + folder3Id = (await apis.user.nodes.createFolder(folder3, parentId)).entry.id; + folder4Id = (await apis.user.nodes.createFolder(folder4, parentId)).entry.id; + folder5Id = (await apis.user.nodes.createFolder(folder5, parentId)).entry.id; + folder6Id = (await apis.user.nodes.createFolder(folder6, parentId)).entry.id; + + await apis.user.nodes.createFile(file1InFolder, folder1Id); + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, folder2Id)).entry.id; fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, folder3Id)).entry.id; - await apis.user.nodes.lockFile(fileLocked2Id); + fileLocked3Id = (await apis.user.nodes.createFile(fileLocked3, folder4Id)).entry.id; + fileLocked4Id = (await apis.user.nodes.createFile(fileLocked4, folder5Id)).entry.id; + await apis.user.nodes.createFile(file2InFolder, folder6Id); - fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1)).entry.id; - await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked1Id, 'FULL'); + await apis.user.nodes.lockFile(fileLocked2Id, 'FULL'); + await apis.user.nodes.lockFile(fileLocked3Id, 'FULL'); + await apis.user.nodes.lockFile(fileLocked4Id, 'FULL'); await loginPage.loginWith(username); + done(); }); beforeEach(async (done) => { await page.clickPersonalFilesAndWait(); - done(); - }); - - afterEach(async (done) => { - await page.refresh(); + await page.dataTable.doubleClickOnRowByName(parent); done(); }); afterAll(async (done) => { - await apis.user.nodes.unlockFile(file4Id); await apis.user.nodes.unlockFile(fileLocked1Id); await apis.user.nodes.unlockFile(fileLocked2Id); - await apis.user.nodes.deleteNodesById([file1Id, file2Id, folder1Id, folder2Id, folder3Id, fileLocked1Id]); - await apis.user.search.waitForApi(username, {expect: 0}); + await apis.user.nodes.unlockFile(fileLocked3Id); + await apis.user.nodes.unlockFile(fileLocked4Id); + await apis.user.nodes.deleteNodeById(parentId); + await apis.user.trashcan.emptyTrash(); done(); }); - xit('delete a file and check notification - [C217125]', async () => { + it('delete a file and check notification - [C217125]', async () => { let items = await page.dataTable.countRows(); - await dataTable.selectItem(file1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`${file1} deleted`); - expect(await dataTable.getRowByName(file1).isPresent()).toBe(false, 'Item was not removed from list'); + expect(message).toContain(`Undo`); + expect(await dataTable.isItemPresent(file1)).toBe(false, 'Item was not removed from list'); items--; - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); await page.clickTrash(); - expect(await dataTable.getRowByName(file1).isPresent()).toBe(true, 'Item is not in trash'); - - await apis.user.trashcan.restore(file1Id); + expect(await dataTable.isItemPresent(file1)).toBe(true, 'Item is not in trash'); }); - xit('delete multiple files and check notification - [C280502]', async () => { + it('delete multiple files and check notification - [C280502]', async () => { let items = await page.dataTable.countRows(); - - await dataTable.selectMultipleItems([file1, file2]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectMultipleItems([file2, file3]); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`Deleted 2 items`); - expect(await dataTable.getRowByName(file1).isPresent()).toBe(false, `${file1} was not removed from list`); - expect(await dataTable.getRowByName(file2).isPresent()).toBe(false, `${file2} was not removed from list`); + expect(await dataTable.isItemPresent(file2)).toBe(false, `${file2} was not removed from list`); + expect(await dataTable.isItemPresent(file3)).toBe(false, `${file3} was not removed from list`); items = items - 2; - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); await page.clickTrash(); - expect(await dataTable.getRowByName(file1).isPresent()).toBe(true, `${file1} is not in trash`); - expect(await dataTable.getRowByName(file2).isPresent()).toBe(true, `${file2} is not in trash`); - - await apis.user.trashcan.restore(file1Id); - await apis.user.trashcan.restore(file2Id); + expect(await dataTable.isItemPresent(file2)).toBe(true, `${file2} is not in trash`); + expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} is not in trash`); }); it('delete a folder with content - [C217126]', async () => { let items = await page.dataTable.countRows(); - await dataTable.selectItem(folder1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); - expect(await dataTable.getRowByName(folder1).isPresent()).toBe(false, 'Item was not removed from list'); + await toolbar.clickMoreActionsDelete(); + expect(await dataTable.isItemPresent(folder1)).toBe(false, 'Item was not removed from list'); items--; - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); await page.clickTrash(); - expect(await dataTable.getRowByName(folder1).isPresent()).toBe(true, 'Item is not in trash'); - expect(await dataTable.getRowByName(file3).isPresent()).toBe(false, 'Item is in trash'); - - await apis.user.trashcan.restore(folder1Id); + expect(await dataTable.isItemPresent(folder1)).toBe(true, 'Item is not in trash'); + expect(await dataTable.isItemPresent(file1InFolder)).toBe(false, 'Item is in trash'); }); it('delete a folder containing locked files - [C217127]', async () => { await dataTable.selectItem(folder2); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`${folder2} couldn't be deleted`); - expect(await dataTable.getRowByName(folder2).isPresent()).toBe(true, 'Item was removed from list'); + expect(message).not.toContain(`Undo`); + expect(await dataTable.isItemPresent(folder2)).toBe(true, 'Item was removed from list'); await page.clickTrash(); - expect(await dataTable.getRowByName(folder2).isPresent()).toBe(false, 'Item is in trash'); - expect(await dataTable.getRowByName(file4).isPresent()).toBe(false, 'Item is in trash'); + expect(await dataTable.isItemPresent(folder2)).toBe(false, 'Item is in trash'); + expect(await dataTable.isItemPresent(fileLocked1)).toBe(false, 'Item is in trash'); }); it('notification on multiple items deletion - some items fail to delete - [C217129]', async () => { - await dataTable.selectMultipleItems([file1, folder2]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectMultipleItems([file4, folder3]); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`Deleted 1 item, 1 couldn't be deleted`); - - await apis.user.trashcan.restore(file1Id); + expect(message).toContain(`Undo`); }); it('notification on multiple items deletion - all items fail to delete - [C217130]', async () => { - await dataTable.selectMultipleItems([folder3, folder2]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectMultipleItems([folder4, folder5]); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toEqual(`2 items couldn't be deleted`); - }); - - it('successful delete notification shows Undo action - [C217131]', async () => { - await dataTable.selectItem(file1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); - const message = await page.getSnackBarMessage(); - expect(message).toContain(`Undo`); - - await apis.user.trashcan.restore(file1Id); - }); - - it('unsuccessful delete notification does not show Undo action - [C217134]', async () => { - await dataTable.selectItem(folder2); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); - const message = await page.getSnackBarMessage(); expect(message).not.toContain(`Undo`); }); it('undo delete of file - [C217132]', async () => { const items = await page.dataTable.countRows(); - await dataTable.selectItem(file1); - await toolbar.openMoreMenu(); - - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectItem(file5); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); - expect(await dataTable.getRowByName(file1).isPresent()).toBe(true, 'Item was not restored'); - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await dataTable.isItemPresent(file5)).toBe(true, 'Item was not restored'); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); }); it('undo delete of folder with content - [C280503]', async () => { const items = await page.dataTable.countRows(); - await dataTable.selectItem(folder1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectItem(folder6); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); - expect(await dataTable.getRowByName(folder1).isPresent()).toBe(true, 'Item was not restored'); - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); - await dataTable.doubleClickOnRowByName(folder1); - expect(await dataTable.getRowByName(file3).isPresent()).toBe(true, 'file from folder not restored'); + expect(await dataTable.isItemPresent(folder6)).toBe(true, 'Item was not restored'); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); + await dataTable.doubleClickOnRowByName(folder6); + expect(await dataTable.isItemPresent(file2InFolder)).toBe(true, 'file from folder not restored'); }); - xit('undo delete of multiple files - [C280504]', async () => { + it('undo delete of multiple files - [C280504]', async () => { const items = await page.dataTable.countRows(); - await dataTable.selectMultipleItems([file1, file2]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectMultipleItems([file6, file7]); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); - expect(await dataTable.getRowByName(file1).isPresent()).toBe(true, `${file1} was not removed from list`); - expect(await dataTable.getRowByName(file2).isPresent()).toBe(true, `${file2} was not removed from list`); - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await dataTable.isItemPresent(file6)).toBe(true, `${file6} was not removed from list`); + expect(await dataTable.isItemPresent(file7)).toBe(true, `${file7} was not removed from list`); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); }); }); @@ -248,14 +234,28 @@ describe('Delete and undo delete', () => { const sharedFile2 = `sharedFile2-${Utils.random()}.txt`; let sharedFile2Id; const sharedFile3 = `sharedFile3-${Utils.random()}.txt`; let sharedFile3Id; const sharedFile4 = `sharedFile4-${Utils.random()}.txt`; let sharedFile4Id; + const sharedFile5 = `sharedFile5-${Utils.random()}.txt`; let sharedFile5Id; + const sharedFile6 = `sharedFile6-${Utils.random()}.txt`; let sharedFile6Id; + + const parent = `parentSF-${Utils.random()}`; let parentId; beforeAll(async (done) => { - sharedFile1Id = (await apis.user.nodes.createFile(sharedFile1)).entry.id; - sharedFile2Id = (await apis.user.nodes.createFile(sharedFile2)).entry.id; - sharedFile3Id = (await apis.user.nodes.createFile(sharedFile3)).entry.id; - sharedFile4Id = (await apis.user.nodes.createFile(sharedFile4)).entry.id; - await apis.user.shared.shareFilesByIds([sharedFile1Id, sharedFile2Id, sharedFile3Id, sharedFile4Id]); - await apis.user.shared.waitForApi({ expect: 4 }); + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + + sharedFile1Id = (await apis.user.nodes.createFile(sharedFile1, parentId)).entry.id; + sharedFile2Id = (await apis.user.nodes.createFile(sharedFile2, parentId)).entry.id; + sharedFile3Id = (await apis.user.nodes.createFile(sharedFile3, parentId)).entry.id; + sharedFile4Id = (await apis.user.nodes.createFile(sharedFile4, parentId)).entry.id; + sharedFile5Id = (await apis.user.nodes.createFile(sharedFile5, parentId)).entry.id; + sharedFile6Id = (await apis.user.nodes.createFile(sharedFile6, parentId)).entry.id; + await apis.user.shared.shareFilesByIds([ + sharedFile1Id, + sharedFile2Id, + sharedFile3Id, + sharedFile4Id, + sharedFile5Id, + sharedFile6Id]); + await apis.user.shared.waitForApi({ expect: 6 }); await loginPage.loginWith(username); done(); @@ -266,109 +266,112 @@ describe('Delete and undo delete', () => { done(); }); - afterEach(async (done) => { - await page.refresh(); - done(); - }); - afterAll(async (done) => { - await apis.user.nodes.deleteNodesById([sharedFile1Id, sharedFile2Id, sharedFile3Id, sharedFile4Id]); - await apis.user.search.waitForApi(username, {expect: 0}); + await apis.user.nodes.deleteNodeById(parentId); + await apis.user.trashcan.emptyTrash(); done(); }); - xit('delete a file and check notification - [C280316]', async () => { + it('delete a file and check notification - [C280316]', async () => { await dataTable.selectItem(sharedFile1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`${sharedFile1} deleted`); - expect(await dataTable.getRowByName(sharedFile1).isPresent()).toBe(false, 'Item was not removed from list'); + expect(message).toContain(`Undo`); + expect(await dataTable.isItemPresent(sharedFile1)).toBe(false, 'Item was not removed from list'); await page.clickTrash(); - expect(await dataTable.getRowByName(sharedFile1).isPresent()).toBe(true, 'Item is not in trash'); - - await apis.user.trashcan.restore(sharedFile1Id); - await apis.user.shared.shareFilesByIds([ sharedFile1Id ]); - await apis.user.shared.waitForApi({ expect: 4 }); + expect(await dataTable.isItemPresent(sharedFile1)).toBe(true, 'Item is not in trash'); }); - xit('delete multiple files and check notification - [C280513]', async () => { + it('delete multiple files and check notification - [C280513]', async () => { await dataTable.selectMultipleItems([sharedFile2, sharedFile3]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`Deleted 2 items`); - expect(await dataTable.getRowByName(sharedFile2).isPresent()).toBe(false, `${sharedFile2} was not removed from list`); - expect(await dataTable.getRowByName(sharedFile3).isPresent()).toBe(false, `${sharedFile3} was not removed from list`); - await page.clickTrash(); - expect(await dataTable.getRowByName(sharedFile2).isPresent()).toBe(true, `${sharedFile2} is not in trash`); - expect(await dataTable.getRowByName(sharedFile3).isPresent()).toBe(true, `${sharedFile3} is not in trash`); - - await apis.user.trashcan.restore(sharedFile2Id); - await apis.user.trashcan.restore(sharedFile3Id); - await apis.user.shared.shareFilesByIds([ sharedFile2Id, sharedFile3Id ]); - await apis.user.shared.waitForApi({ expect: 4 }); - }); - - xit('successful delete notification shows Undo action - [C280323]', async () => { - await dataTable.selectItem(sharedFile1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); - const message = await page.getSnackBarMessage(); expect(message).toContain(`Undo`); - - await apis.user.trashcan.restore(sharedFile1Id); + expect(await dataTable.isItemPresent(sharedFile2)).toBe(false, `${sharedFile2} was not removed from list`); + expect(await dataTable.isItemPresent(sharedFile3)).toBe(false, `${sharedFile3} was not removed from list`); + await page.clickTrash(); + expect(await dataTable.isItemPresent(sharedFile2)).toBe(true, `${sharedFile2} is not in trash`); + expect(await dataTable.isItemPresent(sharedFile3)).toBe(true, `${sharedFile3} is not in trash`); }); - xit('undo delete of file - [C280324]', async () => { - await dataTable.selectItem(sharedFile2); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + it('undo delete of file - [C280324]', async () => { + await dataTable.selectItem(sharedFile4); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); await page.clickTrash(); - expect(await dataTable.getRowByName(sharedFile2).isPresent()).toBe(false, 'Item was not restored'); + expect(await dataTable.isItemPresent(sharedFile4)).toBe(false, 'Item was not restored'); }); - xit('undo delete of multiple files - [C280514]', async () => { - await dataTable.selectMultipleItems([sharedFile3, sharedFile4]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + it('undo delete of multiple files - [C280514]', async () => { + await dataTable.selectMultipleItems([sharedFile5, sharedFile6]); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); await page.clickTrash(); - expect(await dataTable.getRowByName(sharedFile3).isPresent()).toBe(false, `${sharedFile3} was not restored`); - expect(await dataTable.getRowByName(sharedFile4).isPresent()).toBe(false, `${sharedFile4} was not restored`); + expect(await dataTable.isItemPresent(sharedFile5)).toBe(false, `${sharedFile5} was not restored`); + expect(await dataTable.isItemPresent(sharedFile6)).toBe(false, `${sharedFile6} was not restored`); }); }); describe('on Favorites', () => { - const favoriteFile1 = `favFile1-${Utils.random()}.txt`; let favoriteFile1Id; - const favoriteFile2 = `favFile2-${Utils.random()}.txt`; let favoriteFile2Id; - const favoriteFile3 = `favFile3-${Utils.random()}.txt`; - const favoriteFile4 = `favFile4-${Utils.random()}.txt`; let favoriteFile4Id; - const favoriteFolder1 = `favFolder1-${Utils.random()}`; let favoriteFolder1Id; - const favoriteFolder2 = `favFolder2-${Utils.random()}`; let favoriteFolder2Id; - const favoriteFolder3 = `favFolder3-${Utils.random()}`; let favoriteFolder3Id; - const favoriteFileLocked1 = `favFileLocked1-${Utils.random()}.txt`; let favoriteFileLocked1Id; - const favoriteFileLocked2 = `favFileLocked2-${Utils.random()}.txt`; let favoriteFileLocked2Id; + const parent = `parentF-${Utils.random()}`; let parentId; + + const favFile1 = `favFile1-${Utils.random()}.txt`; let favFile1Id; + const favFile2 = `favFile2-${Utils.random()}.txt`; let favFile2Id; + const favFile3 = `favFile3-${Utils.random()}.txt`; let favFile3Id; + const favFile4 = `favFile4-${Utils.random()}.txt`; let favFile4Id; + const favFile5 = `favFile5-${Utils.random()}.txt`; let favFile5Id; + const favFile6 = `favFile6-${Utils.random()}.txt`; let favFile6Id; + const favFile7 = `favFile7-${Utils.random()}.txt`; let favFile7Id; + + const favFolder1 = `favFolder1-${Utils.random()}`; let favFolder1Id; + const favFolder2 = `favFolder2-${Utils.random()}`; let favFolder2Id; + const favFolder3 = `favFolder3-${Utils.random()}`; let favFolder3Id; + const favFolder4 = `favFolder4-${Utils.random()}`; let favFolder4Id; + const favFolder5 = `favFolder5-${Utils.random()}`; let favFolder5Id; + const favFolder6 = `favFolder6-${Utils.random()}`; let favFolder6Id; + + const file1InFolder = `file1InFolder-${Utils.random()}.txt`; + const file2InFolder = `file2InFolder-${Utils.random()}.txt`; + const fileLocked1 = `fileLocked1-${Utils.random()}.txt`; let fileLocked1Id; + const fileLocked2 = `fileLocked2-${Utils.random()}.txt`; let fileLocked2Id; + const fileLocked3 = `fileLocked3-${Utils.random()}.txt`; let fileLocked3Id; + const fileLocked4 = `fileLocked4-${Utils.random()}.txt`; let fileLocked4Id; beforeAll(async (done) => { - favoriteFile1Id = (await apis.user.nodes.createFile(favoriteFile1)).entry.id; - favoriteFile2Id = (await apis.user.nodes.createFile(favoriteFile2)).entry.id; - favoriteFolder1Id = (await apis.user.nodes.createFolder(favoriteFolder1)).entry.id; - favoriteFolder2Id = (await apis.user.nodes.createFolder(favoriteFolder2)).entry.id; - favoriteFolder3Id = (await apis.user.nodes.createFolder(favoriteFolder3)).entry.id; - await apis.user.nodes.createFile(favoriteFile3, favoriteFolder1Id); - favoriteFile4Id = (await apis.user.nodes.createFile(favoriteFile4, favoriteFolder2Id)).entry.id; - favoriteFileLocked2Id = (await apis.user.nodes.createFile(favoriteFileLocked2, favoriteFolder3Id)).entry.id; - await apis.user.nodes.lockFile(favoriteFile4Id); - await apis.user.nodes.lockFile(favoriteFileLocked2Id); - - favoriteFileLocked1Id = (await apis.user.nodes.createFile(favoriteFileLocked1)).entry.id; - await apis.user.nodes.lockFile(favoriteFileLocked1Id); - - await apis.user.favorites.addFavoritesByIds('file', [ favoriteFile1Id, favoriteFile2Id, favoriteFileLocked1Id ]); - await apis.user.favorites.addFavoritesByIds('folder', [ favoriteFolder1Id, favoriteFolder2Id, favoriteFolder3Id ]); - await apis.user.favorites.waitForApi({ expect: 6 }); + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + + favFile1Id = (await apis.user.nodes.createFile(favFile1, parentId)).entry.id; + favFile2Id = (await apis.user.nodes.createFile(favFile2, parentId)).entry.id; + favFile3Id = (await apis.user.nodes.createFile(favFile3, parentId)).entry.id; + favFile4Id = (await apis.user.nodes.createFile(favFile4, parentId)).entry.id; + favFile5Id = (await apis.user.nodes.createFile(favFile5, parentId)).entry.id; + favFile6Id = (await apis.user.nodes.createFile(favFile6, parentId)).entry.id; + favFile7Id = (await apis.user.nodes.createFile(favFile7, parentId)).entry.id; + + favFolder1Id = (await apis.user.nodes.createFolder(favFolder1, parentId)).entry.id; + favFolder2Id = (await apis.user.nodes.createFolder(favFolder2, parentId)).entry.id; + favFolder3Id = (await apis.user.nodes.createFolder(favFolder3, parentId)).entry.id; + favFolder4Id = (await apis.user.nodes.createFolder(favFolder4, parentId)).entry.id; + favFolder5Id = (await apis.user.nodes.createFolder(favFolder5, parentId)).entry.id; + favFolder6Id = (await apis.user.nodes.createFolder(favFolder6, parentId)).entry.id; + + await apis.user.nodes.createFile(file1InFolder, favFolder1Id); + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, favFolder2Id)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, favFolder3Id)).entry.id; + fileLocked3Id = (await apis.user.nodes.createFile(fileLocked3, favFolder4Id)).entry.id; + fileLocked4Id = (await apis.user.nodes.createFile(fileLocked4, favFolder5Id)).entry.id; + await apis.user.nodes.createFile(file2InFolder, favFolder6Id); + + await apis.user.nodes.lockFile(fileLocked1Id, 'FULL'); + await apis.user.nodes.lockFile(fileLocked2Id, 'FULL'); + await apis.user.nodes.lockFile(fileLocked3Id, 'FULL'); + await apis.user.nodes.lockFile(fileLocked4Id, 'FULL'); + + await apis.user.favorites.addFavoritesByIds('file', [ favFile1Id, favFile2Id, favFile3Id, favFile4Id, favFile5Id, favFile6Id, favFile7Id ]); + await apis.user.favorites.addFavoritesByIds('folder', [ favFolder1Id, favFolder2Id, favFolder3Id, favFolder4Id, favFolder5Id, favFolder6Id ]); + await apis.user.favorites.waitForApi({ expect: 13 }); await loginPage.loginWith(username); done(); @@ -379,182 +382,145 @@ describe('Delete and undo delete', () => { done(); }); - afterEach(async (done) => { - await page.refresh(); - done(); - }); - afterAll(async (done) => { - await apis.user.nodes.unlockFile(favoriteFile4Id); - await apis.user.nodes.unlockFile(favoriteFileLocked1Id); - await apis.user.nodes.unlockFile(favoriteFileLocked2Id); - await apis.user.nodes.deleteNodesById([ - favoriteFile1Id, favoriteFile2Id, favoriteFolder1Id, favoriteFolder2Id, favoriteFileLocked1Id, favoriteFolder3Id - ]); - await apis.user.search.waitForApi(username, {expect: 0}); + await apis.user.nodes.unlockFile(fileLocked1Id); + await apis.user.nodes.unlockFile(fileLocked2Id); + await apis.user.nodes.unlockFile(fileLocked3Id); + await apis.user.nodes.unlockFile(fileLocked4Id); + await apis.user.nodes.deleteNodeById(parentId); + await apis.user.trashcan.emptyTrash(); done(); }); - xit('delete a file and check notification - [C280516]', async () => { + it('delete a file and check notification - [C280516]', async () => { let items = await page.dataTable.countRows(); - await dataTable.selectItem(favoriteFile1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectItem(favFile1); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); - expect(message).toContain(`${favoriteFile1} deleted`); - expect(await dataTable.getRowByName(favoriteFile1).isPresent()).toBe(false, 'Item was not removed from list'); + expect(message).toContain(`${favFile1} deleted`); + expect(message).toContain(`Undo`); + expect(await dataTable.isItemPresent(favFile1)).toBe(false, 'Item was not removed from list'); items--; - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); await page.clickTrash(); - expect(await dataTable.getRowByName(favoriteFile1).isPresent()).toBe(true, 'Item is not in trash'); - - await apis.user.trashcan.restore(favoriteFile1Id); + expect(await dataTable.isItemPresent(favFile1)).toBe(true, 'Item is not in trash'); }); - xit('delete multiple files and check notification - [C280517]', async () => { + it('delete multiple files and check notification - [C280517]', async () => { let items = await page.dataTable.countRows(); - await dataTable.selectMultipleItems([favoriteFile1, favoriteFile2]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectMultipleItems([favFile2, favFile3]); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`Deleted 2 items`); - expect(await dataTable.getRowByName(favoriteFile1).isPresent()).toBe(false, `${favoriteFile1} was not removed from list`); - expect(await dataTable.getRowByName(favoriteFile2).isPresent()).toBe(false, `${favoriteFile2} was not removed from list`); + expect(message).toContain(`Undo`); + expect(await dataTable.isItemPresent(favFile2)).toBe(false, `${favFile2} was not removed from list`); + expect(await dataTable.isItemPresent(favFile3)).toBe(false, `${favFile3} was not removed from list`); items = items - 2; - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); await page.clickTrash(); - expect(await dataTable.getRowByName(favoriteFile1).isPresent()).toBe(true, `${favoriteFile1} is not in trash`); - expect(await dataTable.getRowByName(favoriteFile2).isPresent()).toBe(true, `${favoriteFile2} is not in trash`); - - await apis.user.trashcan.restore(favoriteFile1Id); - await apis.user.trashcan.restore(favoriteFile2Id); + expect(await dataTable.isItemPresent(favFile2)).toBe(true, `${favFile2} is not in trash`); + expect(await dataTable.isItemPresent(favFile3)).toBe(true, `${favFile3} is not in trash`); }); it('delete a folder with content - [C280518]', async () => { let items = await page.dataTable.countRows(); - await dataTable.selectItem(favoriteFolder1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); - expect(await dataTable.getRowByName(favoriteFolder1).isPresent()).toBe(false, 'Item was not removed from list'); + await dataTable.selectItem(favFolder1); + await toolbar.clickMoreActionsDelete(); + expect(await dataTable.isItemPresent(favFolder1)).toBe(false, 'Item was not removed from list'); items--; - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); await page.clickTrash(); - expect(await dataTable.getRowByName(favoriteFolder1).isPresent()).toBe(true, 'Item is not in trash'); - expect(await dataTable.getRowByName(favoriteFile3).isPresent()).toBe(false, 'Item is in trash'); - - await apis.user.trashcan.restore(favoriteFolder1Id); + expect(await dataTable.isItemPresent(favFolder1)).toBe(true, 'Item is not in trash'); + expect(await dataTable.isItemPresent(file1InFolder)).toBe(false, 'Item is in trash'); }); it('delete a folder containing locked files - [C280519]', async () => { - await dataTable.selectItem(favoriteFolder2); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectItem(favFolder2); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); - expect(message).toContain(`${favoriteFolder2} couldn't be deleted`); - expect(await dataTable.getRowByName(favoriteFolder2).isPresent()).toBe(true, 'Item was removed from list'); + expect(message).toContain(`${favFolder2} couldn't be deleted`); + expect(await dataTable.isItemPresent(favFolder2)).toBe(true, 'Item was removed from list'); await page.clickTrash(); - expect(await dataTable.getRowByName(favoriteFolder2).isPresent()).toBe(false, 'Item is in trash'); - expect(await dataTable.getRowByName(favoriteFile4).isPresent()).toBe(false, 'Item is in trash'); + expect(await dataTable.isItemPresent(favFolder2)).toBe(false, 'Item is in trash'); + expect(await dataTable.isItemPresent(fileLocked1)).toBe(false, 'Item is in trash'); }); it('notification on multiple items deletion - some items fail to delete - [C280520]', async () => { - await dataTable.selectMultipleItems([favoriteFile1, favoriteFolder2]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectMultipleItems([favFile4, favFolder3]); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`Deleted 1 item, 1 couldn't be deleted`); - - await apis.user.trashcan.restore(favoriteFile1Id); + expect(message).toContain(`Undo`); }); it('notification on multiple items deletion - all items fail to delete - [C280521]', async () => { - await dataTable.selectMultipleItems([favoriteFolder3, favoriteFolder2]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectMultipleItems([favFolder4, favFolder5]); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toEqual(`2 items couldn't be deleted`); - }); - - it('successful delete notification shows Undo action - [C280522]', async () => { - await dataTable.selectItem(favoriteFile1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); - const message = await page.getSnackBarMessage(); - expect(message).toContain(`Undo`); - - await apis.user.trashcan.restore(favoriteFile1Id); - }); - - it('unsuccessful delete notification does not show Undo action - [C280523]', async () => { - await dataTable.selectItem(favoriteFolder2); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); - const message = await page.getSnackBarMessage(); expect(message).not.toContain(`Undo`); }); it('undo delete of file - [C280524]', async () => { const items = await page.dataTable.countRows(); - await dataTable.selectItem(favoriteFile1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectItem(favFile5); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); - expect(await dataTable.getRowByName(favoriteFile1).isPresent()).toBe(true, 'Item was not restored'); - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await dataTable.isItemPresent(favFile5)).toBe(true, 'Item was not restored'); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); }); it('undo delete of folder with content - [C280526]', async () => { const items = await page.dataTable.countRows(); - await dataTable.selectItem(favoriteFolder1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectItem(favFolder6); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); - expect(await dataTable.getRowByName(favoriteFolder1).isPresent()).toBe(true, 'Item was not restored'); - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); - await dataTable.doubleClickOnRowByName(favoriteFolder1); - expect(await dataTable.getRowByName(favoriteFile3).isPresent()).toBe(true, 'file from folder not restored'); + expect(await dataTable.isItemPresent(favFolder6)).toBe(true, 'Item was not restored'); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); + await dataTable.doubleClickOnRowByName(favFolder6); + expect(await dataTable.isItemPresent(file2InFolder)).toBe(true, 'file from folder not restored'); }); it('undo delete of multiple files - [C280525]', async () => { const items = await page.dataTable.countRows(); - await dataTable.selectMultipleItems([favoriteFile1, favoriteFile2]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await dataTable.selectMultipleItems([favFile6, favFile7]); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); - expect(await dataTable.getRowByName(favoriteFile1).isPresent()).toBe(true, `${favoriteFile1} was not removed from list`); - expect(await dataTable.getRowByName(favoriteFile2).isPresent()).toBe(true, `${favoriteFile2} was not removed from list`); - expect(await page.pagination.range.getText()).toContain(`1-${items} of ${items}`); + expect(await dataTable.isItemPresent(favFile6)).toBe(true, `${favFile6} was not removed from list`); + expect(await dataTable.isItemPresent(favFile7)).toBe(true, `${favFile7} was not removed from list`); + expect(await page.pagination.getRange()).toContain(`1-${items} of ${items}`); }); }); - // TODO: try to change search.waitForApi to wait for exact number of items - xdescribe('on Recent Files', () => { - const recentFile1 = `recentFile1-${Utils.random()}.txt`; let recentFile1Id; - const recentFile2 = `recentFile2-${Utils.random()}.txt`; let recentFile2Id; - const recentFile3 = `recentFile3-${Utils.random()}.txt`; let recentFile3Id; - const recentFile4 = `recentFile4-${Utils.random()}.txt`; let recentFile4Id; + describe('on Recent Files', () => { + const parent = `parentRF-${Utils.random()}`; let parentId; + + const recentFile1 = `recentFile1-${Utils.random()}.txt`; + const recentFile2 = `recentFile2-${Utils.random()}.txt`; + const recentFile3 = `recentFile3-${Utils.random()}.txt`; + const recentFile4 = `recentFile4-${Utils.random()}.txt`; + const recentFile5 = `recentFile5-${Utils.random()}.txt`; + const recentFile6 = `recentFile6-${Utils.random()}.txt`; beforeAll(async (done) => { - recentFile1Id = (await apis.user.nodes.createFile(recentFile1)).entry.id; - recentFile2Id = (await apis.user.nodes.createFile(recentFile2)).entry.id; - recentFile3Id = (await apis.user.nodes.createFile(recentFile3)).entry.id; - recentFile4Id = (await apis.user.nodes.createFile(recentFile4)).entry.id; - await apis.user.search.waitForApi(username, { expect: 4 }); + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + + await apis.user.nodes.createFile(recentFile1, parentId); + await apis.user.nodes.createFile(recentFile2, parentId); + await apis.user.nodes.createFile(recentFile3, parentId); + await apis.user.nodes.createFile(recentFile4, parentId); + await apis.user.nodes.createFile(recentFile5, parentId); + await apis.user.nodes.createFile(recentFile6, parentId); + await apis.user.search.waitForApi(username, { expect: 6 }); await loginPage.loginWith(username); await page.clickRecentFiles(); - const empty = await dataTable.isEmptyList(); - if (empty) { - await browser.sleep(6000); - await browser.refresh(); - await page.waitForApp(); - } done(); }); @@ -563,83 +529,59 @@ describe('Delete and undo delete', () => { done(); }); - afterEach(async (done) => { - await page.refresh(); - done(); - }); - afterAll(async (done) => { - await apis.user.nodes.deleteNodesById([recentFile1Id, recentFile2Id, recentFile3Id, recentFile4Id]); + await apis.user.nodes.deleteNodeById(parentId); + await apis.user.trashcan.emptyTrash(); done(); }); - xit('delete a file and check notification - [C280528]', async () => { + it('delete a file and check notification - [C280528]', async () => { await dataTable.selectItem(recentFile1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`${recentFile1} deleted`); - expect(await dataTable.getRowByName(recentFile1).isPresent()).toBe(false, 'Item was not removed from list'); + expect(message).toContain(`Undo`); + expect(await dataTable.isItemPresent(recentFile1)).toBe(false, 'Item was not removed from list'); await page.clickTrash(); - expect(await dataTable.getRowByName(recentFile1).isPresent()).toBe(true, 'Item is not in trash'); - - await apis.user.trashcan.restore(recentFile1Id); - await apis.user.search.waitForApi(username, { expect: 4 }); + expect(await dataTable.isItemPresent(recentFile1)).toBe(true, 'Item is not in trash'); }); - xit('delete multiple files and check notification - [C280529]', async () => { + it('delete multiple files and check notification - [C280529]', async () => { await dataTable.selectMultipleItems([recentFile2, recentFile3]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); const message = await page.getSnackBarMessage(); expect(message).toContain(`Deleted 2 items`); - expect(await dataTable.getRowByName(recentFile2).isPresent()).toBe(false, `${recentFile2} was not removed from list`); - expect(await dataTable.getRowByName(recentFile3).isPresent()).toBe(false, `${recentFile3} was not removed from list`); - await page.clickTrash(); - expect(await dataTable.getRowByName(recentFile2).isPresent()).toBe(true, `${recentFile2} is not in trash`); - expect(await dataTable.getRowByName(recentFile3).isPresent()).toBe(true, `${recentFile3} is not in trash`); - - await apis.user.trashcan.restore(recentFile2Id); - await apis.user.trashcan.restore(recentFile3Id); - await apis.user.search.waitForApi(username, { expect: 4 }); - }); - - xit('successful delete notification shows Undo action - [C280534]', async () => { - await dataTable.selectItem(recentFile1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); - const message = await page.getSnackBarMessage(); expect(message).toContain(`Undo`); - - await apis.user.trashcan.restore(recentFile1Id); - await apis.user.search.waitForApi(username, { expect: 4 }); + expect(await dataTable.isItemPresent(recentFile2)).toBe(false, `${recentFile2} was not removed from list`); + expect(await dataTable.isItemPresent(recentFile3)).toBe(false, `${recentFile3} was not removed from list`); + await page.clickTrash(); + expect(await dataTable.isItemPresent(recentFile2)).toBe(true, `${recentFile2} is not in trash`); + expect(await dataTable.isItemPresent(recentFile3)).toBe(true, `${recentFile3} is not in trash`); }); // due to the fact that the search api is slow to update, // we cannot test that the restored file is displayed in the Recent Files list // without adding a very big browser.sleep followed by a page.refresh // so for the moment we're testing that the restored file is not displayed in the Trash - xit('undo delete of file - [C280536]', async () => { - await dataTable.selectItem(recentFile2); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + it('undo delete of file - [C280536]', async () => { + await dataTable.selectItem(recentFile4); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); await page.clickTrash(); - expect(await dataTable.getRowByName(recentFile2).isPresent()).toBe(false, 'Item is in Trash'); + expect(await dataTable.isItemPresent(recentFile4)).toBe(false, 'Item is in Trash'); }); // due to the fact that the search api is slow to update, // we cannot test that the restored file is displayed in the Recent Files list // without adding a very big browser.sleep followed by a page.refresh // so for the moment we're testing that the restored file is not displayed in the Trash - xit('undo delete of multiple files - [C280537]', async () => { - await dataTable.selectMultipleItems([recentFile3, recentFile4]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + it('undo delete of multiple files - [C280537]', async () => { + await dataTable.selectMultipleItems([recentFile5, recentFile6]); + await toolbar.clickMoreActionsDelete(); await page.clickSnackBarAction(); await page.clickTrash(); - expect(await dataTable.getRowByName(recentFile3).isPresent()).toBe(false, `${recentFile3} is in Trash`); - expect(await dataTable.getRowByName(recentFile4).isPresent()).toBe(false, `${recentFile4} is in Trash`); + expect(await dataTable.isItemPresent(recentFile5)).toBe(false, `${recentFile5} is in Trash`); + expect(await dataTable.isItemPresent(recentFile6)).toBe(false, `${recentFile6} is in Trash`); }); }); }); diff --git a/e2e/suites/actions/download.test.ts b/e2e/suites/actions/download.test.ts new file mode 100755 index 0000000000..8391e010e1 --- /dev/null +++ b/e2e/suites/actions/download.test.ts @@ -0,0 +1,315 @@ +/*! + * @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 . + */ + +import { LoginPage, BrowsingPage, SearchResultsPage } from '../../pages/pages'; +import { RepoClient } from '../../utilities/repo-client/repo-client'; +import { Utils } from '../../utilities/utils'; + +describe('Download', () => { + const username = `user-${Utils.random()}`; + + const parent = `parent-${Utils.random()}`; let parentId; + + const filePersonal = `filePersonal-${Utils.random()}.txt`; + const fileRecent1 = `fileRecent1-${Utils.random()}.txt`; + const fileRecent2 = `fileRecent2-${Utils.random()}.txt`; + const fileShared1 = `fileShared1-${Utils.random()}.txt`; + const fileShared2 = `fileShared2-${Utils.random()}.txt`; + const fileFavorites = `fileFavorites-${Utils.random()}.txt`; + const fileSearch = `fileSearch-${Utils.random()}.txt`; + + const folderPersonal = `folderPersonal-${Utils.random()}`; + const folderFavorites = `folderFavorites-${Utils.random()}`; + const folderSearch = `folderSearch-${Utils.random()}`; + + const fileInFolderPersonal = `fileInFolderPersonal-${Utils.random()}.txt`; + const fileInFolderFavorites = `fileInFolderFavorites-${Utils.random()}.txt`; + const fileInFolderSearch = `fileInFolderSearch-${Utils.random()}.txt`; + + const unzippedPersonal = `unzippedPersonal-${Utils.random()}`; + const unzippedRecent = `unzippedRecent-${Utils.random()}`; + const unzippedShared = `unzippedShared-${Utils.random()}`; + const unzippedFavorites = `unzippedFavorites-${Utils.random()}`; + const unzippedSearch = `unzippedSearch-${Utils.random()}`; + + let fileShared1Id, fileShared2Id, fileFavoritesId, folderPersonalId, folderFavoritesId, folderSearchId; + + const archiveZip = 'archive.zip'; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable, toolbar } = page; + const searchResultsPage = new SearchResultsPage(); + const { searchInput } = searchResultsPage.header; + + beforeAll(async done => { + await apis.admin.people.createUser({ username }); + + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + + await apis.user.nodes.createFile(filePersonal, parentId); + await apis.user.nodes.createFile(fileRecent1, parentId); + await apis.user.nodes.createFile(fileRecent2, parentId); + fileShared1Id = (await apis.user.nodes.createFile(fileShared1, parentId)).entry.id; + fileShared2Id = (await apis.user.nodes.createFile(fileShared2, parentId)).entry.id; + fileFavoritesId = (await apis.user.nodes.createFile(fileFavorites, parentId)).entry.id; + await apis.user.nodes.createFile(fileSearch, parentId); + + folderPersonalId = (await apis.user.nodes.createFolder(folderPersonal, parentId)).entry.id; + await apis.user.nodes.createFile(fileInFolderPersonal, folderPersonalId); + + folderFavoritesId = (await apis.user.nodes.createFolder(folderFavorites, parentId)).entry.id; + await apis.user.nodes.createFile(fileInFolderFavorites, folderFavoritesId); + + folderSearchId = (await apis.user.nodes.createFolder(folderSearch, parentId)).entry.id; + await apis.user.nodes.createFile(fileInFolderSearch, folderSearchId); + + await apis.user.shared.shareFileById(fileShared1Id); + await apis.user.shared.shareFileById(fileShared2Id); + await apis.user.favorites.addFavoriteById('file', fileFavoritesId); + await apis.user.favorites.addFavoriteById('folder', folderFavoritesId); + + await loginPage.loginWith(username); + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentId); + await apis.user.trashcan.emptyTrash(); + done(); + }); + + afterEach(async (done) => { + await Utils.renameFile(archiveZip, `${Utils.random()}.zip`); + done(); + }); + + describe('on Personal Files', () => { + + beforeEach(async (done) => { + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parent); + done(); + }); + + it('Download a file - [C213179]', async () => { + await dataTable.selectItem(filePersonal); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(filePersonal)).toBe(true, 'File not found in download location'); + }); + + it('Download a folder - [C216352]', async () => { + await dataTable.selectItem(folderPersonal); + await toolbar.clickDownload(); + + const folderZip = `${folderPersonal}.zip`; + + expect(await Utils.fileExistsOnOS(folderZip)).toBe(true, 'File not found in download location'); + + await Utils.unzip(folderZip); + + expect(await Utils.fileExistsOnOS(fileInFolderPersonal, folderPersonal)); + }); + + it('Download multiple items - [C216353]', async () => { + await dataTable.selectMultipleItems([filePersonal, folderPersonal]); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(archiveZip)).toBe(true, 'File not found in download location'); + + await Utils.unzip(archiveZip, unzippedPersonal); + + expect(await Utils.fileExistsOnOS(filePersonal, unzippedPersonal)).toBe(true, `${filePersonal} not found in unzipped folder`); + expect(await Utils.fileExistsOnOS(folderPersonal, unzippedPersonal)).toBe(true, `${folderPersonal} not found in unzipped folder`); + expect(await Utils.fileExistsOnOS(fileInFolderPersonal, unzippedPersonal, folderPersonal)).toBe(true, `${fileInFolderPersonal} not found in unzipped folder in ${folderPersonal}`) + }); + + }); + + describe('on Favorites', () => { + + beforeAll(async (done) => { + await apis.user.favorites.waitForApi({ expect: 2 }); + done(); + }); + + beforeEach(async (done) => { + await page.clickFavoritesAndWait(); + done(); + }); + + it('Download a file - [C280173]', async () => { + await dataTable.selectItem(fileFavorites); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(fileFavorites)).toBe(true, 'File not found in download location'); + }); + + it('Download a folder - [C280188]', async () => { + await dataTable.selectItem(folderFavorites); + await toolbar.clickDownload(); + + const folderZip = `${folderFavorites}.zip`; + + expect(await Utils.fileExistsOnOS(folderZip)).toBe(true, 'File not found in download location'); + + await Utils.unzip(folderZip); + + expect(await Utils.fileExistsOnOS(fileInFolderFavorites, folderFavorites)); + }); + + it('Download multiple items - [C280189]', async () => { + await dataTable.selectMultipleItems([fileFavorites, folderFavorites]); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(archiveZip)).toBe(true, 'File not found in download location'); + + await Utils.unzip(archiveZip, unzippedFavorites); + + expect(await Utils.fileExistsOnOS(fileFavorites, unzippedFavorites)).toBe(true, `${fileFavorites} not found in unzipped folder`); + expect(await Utils.fileExistsOnOS(folderFavorites, unzippedFavorites)).toBe(true, `${folderFavorites} not found in unzipped folder`); + expect(await Utils.fileExistsOnOS(fileInFolderFavorites, unzippedFavorites, folderFavorites)).toBe(true, `${fileInFolderFavorites} not found in unzipped folder in ${folderFavorites}`) + }); + + }); + + describe('on Shared Files', () => { + + beforeAll(async (done) => { + await apis.user.shared.waitForApi({ expect: 2 }); + done(); + }); + + beforeEach(async (done) => { + await page.clickSharedFilesAndWait(); + done(); + }); + + it('Download a file - [C280170]', async () => { + await dataTable.selectItem(fileShared1); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(fileShared1)).toBe(true, 'File not found in download location'); + }); + + it('Download multiple items - [C280183]', async () => { + await dataTable.selectMultipleItems([fileShared1, fileShared2]); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(archiveZip)).toBe(true, 'File not found in download location'); + + await Utils.unzip(archiveZip, unzippedShared); + + expect(await Utils.fileExistsOnOS(fileShared1, unzippedShared)).toBe(true, `${fileShared1} not found in unzipped folder`); + expect(await Utils.fileExistsOnOS(fileShared2, unzippedShared)).toBe(true, `${fileShared2} not found in unzipped folder`); + }); + + }); + + describe('on Recent Files', () => { + + beforeAll(async (done) => { + await apis.user.search.waitForApi(username, { expect: 10 }); + done(); + }); + + beforeEach(async (done) => { + await page.clickRecentFilesAndWait(); + done(); + }); + + it('Download a file - [C280167]', async () => { + await dataTable.selectItem(fileRecent1); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(fileRecent1)).toBe(true, 'File not found in download location'); + }); + + it('Download multiple items - [C280177]', async () => { + await dataTable.selectMultipleItems([fileRecent1, fileRecent2]); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(archiveZip)).toBe(true, 'File not found in download location'); + + await Utils.unzip(archiveZip, unzippedRecent); + + expect(await Utils.fileExistsOnOS(fileRecent1, unzippedRecent)).toBe(true, `${fileRecent1} not found in unzipped folder`); + expect(await Utils.fileExistsOnOS(fileRecent2, unzippedRecent)).toBe(true, `${fileRecent2} not found in unzipped folder`); + }); + + }); + + describe('on Search Results', () => { + + beforeEach(async (done) => { + await page.clickPersonalFilesAndWait(); + await searchInput.clickSearchButton(); + await searchInput.checkFilesAndFolders(); + await searchInput.searchForTextAndCloseSearchOptions('*Search*'); + done(); + }); + + it('Download a file - [C279164]', async () => { + await dataTable.selectItem(fileSearch, parent); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(fileSearch)).toBe(true, 'File not found in download location'); + }); + + it('Download a folder - [C297694]', async () => { + await dataTable.selectItem(folderSearch, parent); + await toolbar.clickDownload(); + + const folderZip = `${folderSearch}.zip`; + + expect(await Utils.fileExistsOnOS(folderZip)).toBe(true, 'File not found in download location'); + + await Utils.unzip(folderZip); + + expect(await Utils.fileExistsOnOS(fileInFolderSearch, folderSearch)); + }); + + it('Download multiple items - [C297695]', async () => { + await dataTable.selectMultipleItems([fileSearch, folderSearch], parent); + await toolbar.clickDownload(); + + expect(await Utils.fileExistsOnOS(archiveZip)).toBe(true, 'File not found in download location'); + + await Utils.unzip(archiveZip, unzippedSearch); + + expect(await Utils.fileExistsOnOS(fileSearch, unzippedSearch)).toBe(true, `${fileSearch} not found in unzipped folder`); + expect(await Utils.fileExistsOnOS(folderSearch, unzippedSearch)).toBe(true, `${folderSearch} not found in unzipped folder`); + expect(await Utils.fileExistsOnOS(fileInFolderSearch, unzippedSearch, folderSearch)).toBe(true, `${fileInFolderSearch} not found in unzipped folder in ${folderSearch}`) + }); + + }); + +}); diff --git a/e2e/suites/actions/edit-folder.test.ts b/e2e/suites/actions/edit-folder.test.ts index 5342bac45b..e66128c630 100755 --- a/e2e/suites/actions/edit-folder.test.ts +++ b/e2e/suites/actions/edit-folder.test.ts @@ -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 @@ -62,8 +62,7 @@ describe('Edit folder', () => { const loginPage = new LoginPage(); const page = new BrowsingPage(); const editDialog = new CreateOrEditFolderDialog(); - const { dataTable } = page; - const editButton = page.toolbar.getButtonByTitleAttribute('Edit'); + const { dataTable, toolbar } = page; beforeAll(async (done) => { await apis.admin.people.createUser({ username }); @@ -112,12 +111,14 @@ describe('Edit folder', () => { it('dialog UI defaults - [C216331]', async () => { await dataTable.doubleClickOnRowByName(parent); await dataTable.selectItem(folderName); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); + expect(await editDialog.getTitle()).toEqual('Edit folder'); - expect(await editDialog.nameInput.getAttribute('value')).toBe(folderName); - expect(await editDialog.descriptionTextArea.getAttribute('value')).toBe(folderDescription); - expect(await editDialog.updateButton.isEnabled()).toBe(true, 'upload button is not enabled'); - expect(await editDialog.cancelButton.isEnabled()).toBe(true, 'cancel button is not enabled'); + expect(await editDialog.getName()).toBe(folderName); + expect(await editDialog.getDescription()).toBe(folderDescription); + expect(await editDialog.isUpdateButtonEnabled()).toBe(true, 'upload button is not enabled'); + expect(await editDialog.isCancelButtonEnabled()).toBe(true, 'cancel button is not enabled'); }); describe('on Personal Files', () => { @@ -130,14 +131,16 @@ describe('Edit folder', () => { it('properties are modified when pressing OK - [C216335]', async (done) => { await dataTable.selectItem(folderNameToEdit); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.waitForDialogToOpen(); await editDialog.enterDescription(folderDescriptionEdited); await editDialog.enterName(folderNameEdited); await editDialog.clickUpdate(); await editDialog.waitForDialogToClose(); await dataTable.waitForHeader(); - expect(await dataTable.getRowByName(folderNameEdited).isPresent()).toBe(true, 'Folder not displayed'); + + expect(await dataTable.isItemPresent(folderNameEdited)).toBe(true, 'Folder not displayed'); const desc = await apis.user.nodes.getNodeDescription(folderNameEdited, parentId); expect(desc).toEqual(folderDescriptionEdited); done(); @@ -145,9 +148,11 @@ describe('Edit folder', () => { it('with empty folder name - [C216332]', async () => { await dataTable.selectItem(folderName); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.deleteNameWithBackspace(); - expect(await editDialog.updateButton.isEnabled()).toBe(false, 'upload button is not enabled'); + + expect(await editDialog.isUpdateButtonEnabled()).toBe(false, 'upload button is not enabled'); expect(await editDialog.getValidationMessage()).toMatch('Folder name is required'); }); @@ -155,51 +160,59 @@ describe('Edit folder', () => { const namesWithSpecialChars = [ 'a*a', 'a"a', 'aa', `a\\a`, 'a/a', 'a?a', 'a:a', 'a|a' ]; await dataTable.selectItem(folderName); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); for (const name of namesWithSpecialChars) { await editDialog.enterName(name); - expect(await editDialog.updateButton.isEnabled()).toBe(false, 'upload button is not disabled'); + expect(await editDialog.isUpdateButtonEnabled()).toBe(false, 'upload button is not disabled'); expect(await editDialog.getValidationMessage()).toContain(`Folder name can't contain these characters`); } }); it('with name ending with a dot - [C216334]', async () => { await dataTable.selectItem(folderName); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.waitForDialogToOpen(); await editDialog.nameInput.sendKeys('.'); - expect(await editDialog.updateButton.isEnabled()).toBe(false, 'upload button is not enabled'); + + expect(await editDialog.isUpdateButtonEnabled()).toBe(false, 'upload button is not enabled'); expect(await editDialog.getValidationMessage()).toMatch(`Folder name can't end with a period .`); }); it('Cancel button - [C216336]', async () => { await dataTable.selectItem(folderName); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.waitForDialogToOpen(); await editDialog.clickCancel(); + expect(await editDialog.isDialogOpen()).not.toBe(true, 'dialog is not closed'); }); it('with duplicate folder name - [C216337]', async () => { await dataTable.selectItem(folderName); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.waitForDialogToOpen(); await editDialog.enterName(duplicateFolderName); await editDialog.clickUpdate(); - 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 editDialog.isDialogOpen()).toBe(true, 'dialog is not present'); }); it('trim ending spaces - [C216338]', async () => { await dataTable.selectItem(folderName); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.nameInput.sendKeys(' '); await editDialog.clickUpdate(); await editDialog.waitForDialogToClose(); - expect(await page.snackBar.isPresent()).not.toBe(true, 'notification appears'); - expect(await dataTable.getRowByName(folderName).isPresent()).toBe(true, 'Folder not displayed in list view'); + + expect(await page.isSnackBarPresent()).not.toBe(true, 'notification appears'); + expect(await dataTable.isItemPresent(folderName)).toBe(true, 'Folder not displayed in list view'); }); }); @@ -211,14 +224,16 @@ describe('Edit folder', () => { it('properties are modified when pressing OK - [C280384]', async (done) => { await dataTable.selectItem(folderFavoriteToEdit); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.waitForDialogToOpen(); await editDialog.enterDescription(folderDescriptionEdited); await editDialog.enterName(folderNameEdited); await editDialog.clickUpdate(); await editDialog.waitForDialogToClose(); await dataTable.waitForHeader(); - expect(await dataTable.getRowByName(folderNameEdited).isPresent()).toBe(true, 'Folder not displayed'); + + expect(await dataTable.isItemPresent(folderNameEdited)).toBe(true, 'Folder not displayed'); const desc = await apis.user.nodes.getNodeProperty(folderFavoriteToEditId, 'cm:description'); expect(desc).toEqual(folderDescriptionEdited); done(); @@ -226,33 +241,36 @@ describe('Edit folder', () => { it('with duplicate folder name - [C280386]', async () => { await dataTable.selectItem(folderFavorite); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.waitForDialogToOpen(); await editDialog.enterName(folderFavoriteDuplicate); await editDialog.clickUpdate(); - 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 editDialog.isDialogOpen()).toBe(true, 'dialog is not present'); }); }); describe('on My Libraries', () => { beforeEach(async (done) => { - await page.clickFileLibrariesAndWait(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); done(); }); it('properties are modified when pressing OK - [C280509]', async (done) => { await dataTable.selectItem(folderSiteToEdit); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.waitForDialogToOpen(); await editDialog.enterDescription(folderDescriptionEdited); await editDialog.enterName(folderNameEdited); await editDialog.clickUpdate(); await editDialog.waitForDialogToClose(); await dataTable.waitForHeader(); - expect(await dataTable.getRowByName(folderNameEdited).isPresent()).toBe(true, 'Folder not displayed'); + + expect(await dataTable.isItemPresent(folderNameEdited)).toBe(true, 'Folder not displayed'); const desc = await apis.user.nodes.getNodeProperty(folderSiteToEditId, 'cm:description'); expect(desc).toEqual(folderDescriptionEdited); done(); @@ -260,12 +278,13 @@ describe('Edit folder', () => { it('with duplicate folder name - [C280511]', async () => { await dataTable.selectItem(folderSite); - await editButton.click(); + await toolbar.openMoreMenu(); + await toolbar.menu.clickEditFolder(); await editDialog.waitForDialogToOpen(); await editDialog.enterName(duplicateFolderSite); await editDialog.clickUpdate(); - 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 editDialog.isDialogOpen()).toBe(true, 'dialog is not present'); }); }); diff --git a/e2e/suites/actions/edit-offline.test.ts b/e2e/suites/actions/edit-offline.test.ts new file mode 100755 index 0000000000..96e5ecb91a --- /dev/null +++ b/e2e/suites/actions/edit-offline.test.ts @@ -0,0 +1,270 @@ +/*! + * @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 . + */ + +import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { FILES } from '../../configs'; +import { RepoClient } from '../../utilities/repo-client/repo-client'; +import { Utils } from '../../utilities/utils'; + +describe('Edit offline', () => { + const username = `user-${Utils.random()}`; + + const file1 = `file1-${Utils.random()}.docx`; let file1Id; + const fileLocked = `file-locked-${Utils.random()}.docx`; let fileLockedId; + const fileLocked2 = `file-locked2-${Utils.random()}.docx`; let fileLocked2Id; + + const parentPF = `parentPersonal-${Utils.random()}`; let parentPFId; + const parentSF = `parentShared-${Utils.random()}`; let parentSFId; + const parentRF = `parentRecent-${Utils.random()}`; let parentRFId; + const parentFav = `parentFav-${Utils.random()}`; let parentFavId; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable, toolbar } = page; + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + + parentPFId = (await apis.user.nodes.createFolder(parentPF)).entry.id; + parentSFId = (await apis.user.nodes.createFolder(parentSF)).entry.id; + parentRFId = (await apis.user.nodes.createFolder(parentRF)).entry.id; + parentFavId = (await apis.user.nodes.createFolder(parentFav)).entry.id; + + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentPFId); + await apis.user.nodes.deleteNodeById(parentSFId); + await apis.user.nodes.deleteNodeById(parentRFId); + await apis.user.nodes.deleteNodeById(parentFavId); + done(); + }); + + describe('on Personal Files', () => { + beforeAll(async (done) => { + file1Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentPFId, file1)).entry.id; + fileLockedId = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentPFId, fileLocked)).entry.id; + fileLocked2Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentPFId, fileLocked2)).entry.id; + + await apis.user.nodes.lockFile(fileLockedId); + await apis.user.nodes.lockFile(fileLocked2Id); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parentPF); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('File is locked and downloaded when clicking Edit Offline - [C297538]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(file1)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(file1Id)).toBe(true, `${file1} is not locked`); + }); + + it('Lock information is displayed - [C297539]', async () => { + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, `${fileLocked2} is not displayed`); + expect(await dataTable.hasLockIcon(fileLocked2)).toBe(true, `${fileLocked2} does not have a lock icon`); + expect(await dataTable.getLockOwner(fileLocked2)).toContain(username, `${fileLocked2} does not have correct lock owner info`); + }); + + it('Cancel Editing unlocks the file - [C297540]', async () => { + await dataTable.selectItem(fileLocked); + await toolbar.clickMoreActionsCancelEditing(); + await dataTable.clearSelection(); + + expect(await apis.user.nodes.isFileLockedWrite(fileLockedId)).toBe(false, `${fileLocked} is still locked`); + expect(await dataTable.hasLockIcon(fileLocked)).toBe(false, `${fileLocked} has a lock icon`); + }); + }); + + // TODO: enable tests when ACA-2173 is done + xdescribe('on Shared Files', () => { + beforeAll(async (done) => { + file1Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentSFId, file1)).entry.id; + fileLockedId = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentSFId, fileLocked)).entry.id; + fileLocked2Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentSFId, fileLocked2)).entry.id; + + await apis.user.nodes.lockFile(fileLockedId); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.shared.shareFilesByIds([file1Id, fileLockedId, fileLocked2Id]); + await apis.user.shared.waitForApi({ expect: 3 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickSharedFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + xit('File is locked and downloaded when clicking Edit Offline - []', async () => { + await dataTable.selectItem(file1, parentSF); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(file1)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(file1Id)).toBe(true, `${file1} is not locked`); + }); + + xit('Lock information is displayed - []', async () => { + expect(await dataTable.isItemPresent(fileLocked2, parentSF)).toBe(true, `${fileLocked2} is not displayed`); + expect(await dataTable.hasLockIcon(fileLocked2, parentSF)).toBe(true, `${fileLocked2} does not have a lock icon`); + expect(await dataTable.getLockOwner(fileLocked2, parentSF)).toContain(username, `${fileLocked2} does not have correct lock owner info`); + }); + + xit('Cancel Editing unlocks the file - []', async () => { + await dataTable.selectItem(fileLocked); + await toolbar.clickMoreActionsCancelEditing(); + await dataTable.clearSelection(); + + expect(await apis.user.nodes.isFileLockedWrite(fileLockedId)).toBe(false, `${fileLocked} is still locked`); + expect(await dataTable.hasLockIcon(fileLocked, parentSF)).toBe(false, `${fileLocked} has a lock icon`); + }); + }); + + describe('on Recent Files', () => { + beforeAll(async (done) => { + file1Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentRFId, file1)).entry.id; + fileLockedId = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentRFId, fileLocked)).entry.id; + fileLocked2Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentRFId, fileLocked2)).entry.id; + + await apis.user.nodes.lockFile(fileLockedId); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.search.waitForApi(username, { expect: 6 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickRecentFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('File is locked and downloaded when clicking Edit Offline - [C297541]', async () => { + await dataTable.selectItem(file1, parentRF); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(file1)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(file1Id)).toBe(true, `${file1} is not locked`); + }); + + it('Lock information is displayed - [C297542]', async () => { + expect(await dataTable.isItemPresent(fileLocked2, parentRF)).toBe(true, `${fileLocked2} is not displayed`); + expect(await dataTable.hasLockIcon(fileLocked2, parentRF)).toBe(true, `${fileLocked2} does not have a lock icon`); + expect(await dataTable.getLockOwner(fileLocked2, parentRF)).toContain(username, `${fileLocked2} does not have correct lock owner info`); + }); + + it('Cancel Editing unlocks the file - [C297543]', async () => { + await dataTable.selectItem(fileLocked, parentRF); + await toolbar.clickMoreActionsCancelEditing(); + await dataTable.clearSelection(); + + expect(await apis.user.nodes.isFileLockedWrite(fileLockedId)).toBe(false, `${fileLocked} is still locked`); + expect(await dataTable.hasLockIcon(fileLocked, parentRF)).toBe(false, `${fileLocked} has a lock icon`); + }); + }); + + // TODO: enable tests when ACA-2174 is done + xdescribe('on Favorite Files', () => { + beforeAll(async (done) => { + file1Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentFavId, file1)).entry.id; + fileLockedId = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentFavId, fileLocked)).entry.id; + fileLocked2Id = (await apis.user.upload.uploadFileWithRename(FILES.docxFile, parentFavId, fileLocked2)).entry.id; + + await apis.user.nodes.lockFile(fileLockedId); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.favorites.addFavoritesByIds('file', [file1Id, fileLockedId, fileLocked2Id]); + await apis.user.favorites.waitForApi({ expect: 3 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickFavoritesAndWait(); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + xit('File is locked and downloaded when clicking Edit Offline - []', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(file1)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(file1Id)).toBe(true, `${file1} is not locked`); + }); + + xit('Lock information is displayed - []', async () => { + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, `${fileLocked2} is not displayed`); + expect(await dataTable.hasLockIcon(fileLocked2)).toBe(true, `${fileLocked2} does not have a lock icon`); + expect(await dataTable.getLockOwner(fileLocked2)).toContain(username, `${fileLocked2} does not have correct lock owner info`); + }); + + xit('Cancel Editing unlocks the file - []', async () => { + await dataTable.selectItem(fileLocked); + await toolbar.clickMoreActionsCancelEditing(); + await dataTable.clearSelection(); + + expect(await apis.user.nodes.isFileLockedWrite(fileLockedId)).toBe(false, `${fileLocked} is still locked`); + expect(await dataTable.hasLockIcon(fileLocked)).toBe(false, `${fileLocked} has a lock icon`); + }); + }); + +}); diff --git a/e2e/suites/actions/library-actions.test.ts b/e2e/suites/actions/library-actions.test.ts index 7a32a55903..1bc988c4cc 100755 --- a/e2e/suites/actions/library-actions.test.ts +++ b/e2e/suites/actions/library-actions.test.ts @@ -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 @@ -96,89 +96,85 @@ describe('Library actions', () => { }); it('Join a public library - Favorite Libraries - [C290105]', async () => { - await page.goToFavoriteLibraries(); + await page.goToFavoriteLibrariesAndWait(); await dataTable.selectItem(sitePublic1Admin); - await toolbar.clickButton('Join'); - const role = await dataTable.getLibraryRole(sitePublic1Admin); - expect(role).toEqual('Consumer'); + await toolbar.clickJoin(); + + expect(await dataTable.getLibraryRole(sitePublic1Admin)).toEqual('Consumer'); }); it('Join a moderated library - Favorite Libraries - [C290109]', async () => { - await page.goToFavoriteLibraries(); + await page.goToFavoriteLibrariesAndWait(); await dataTable.selectItem(siteModerated1Admin); - await toolbar.clickButton('Join'); - const role = await dataTable.getLibraryRole(siteModerated1Admin); - expect(role).toEqual(''); + await toolbar.clickJoin(); + + expect(await dataTable.getLibraryRole(siteModerated1Admin)).toEqual(''); const hasJoinRequest = await apis.user.sites.hasMembershipRequest(siteModerated1Admin); expect(hasJoinRequest).toBe(true, `Join request does not exist on ${siteModerated1Admin}`); }); it('Leave a library - My Libraries - [C290106]', async () => { - await page.goToMyLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.selectItem(sitePublic2Admin); - await toolbar.clickButton('Leave library'); + await toolbar.clickLeave(); await page.waitForDialog(); - await confirmDialog.clickButton('OK'); - const text = await page.getSnackBarMessage(); + await confirmDialog.clickOk(); - expect(text).toEqual(`You have left the library`); - expect(await dataTable.getRowByName(sitePublic2Admin).isPresent()).toBe(false, `${sitePublic2Admin} is displayed`); + expect(await page.getSnackBarMessage()).toEqual(`You have left the library`); + expect(await dataTable.isItemPresent(sitePublic2Admin)).toBe(false, `${sitePublic2Admin} is displayed`); }); it('Leave a library - Favorite Libraries - [C290110]', async () => { - await page.goToFavoriteLibraries(); + await page.goToFavoriteLibrariesAndWait(); await dataTable.selectItem(sitePublic3Admin); - await toolbar.clickButton('Leave library'); + await toolbar.clickLeave(); await page.waitForDialog(); - await confirmDialog.clickButton('OK'); - const text = await page.getSnackBarMessage(); + await confirmDialog.clickOk(); - expect(text).toEqual(`You have left the library`); - expect(await dataTable.getRowByName(sitePublic3Admin).isPresent()).toBe(true, `${sitePublic3Admin} is not displayed`); + expect(await page.getSnackBarMessage()).toEqual(`You have left the library`); + expect(await dataTable.isItemPresent(sitePublic3Admin)).toBe(true, `${sitePublic3Admin} is not displayed`); }); it('Confirmation dialog UI - [C290136]', async () => { - await page.goToMyLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.selectItem(sitePublic4Admin); - await toolbar.clickButton('Leave library'); + await toolbar.clickLeave(); await page.waitForDialog(); expect(await confirmDialog.isDialogOpen()).toBe(true, 'Confirm delete dialog not open'); expect(await confirmDialog.getTitle()).toContain('Leave this library?'); expect(await confirmDialog.getText()).toContain('Leaving will remove your access.'); - expect(await confirmDialog.isButtonEnabled('OK')).toBe(true, 'OK button is not enabled'); - expect(await confirmDialog.isButtonEnabled('Cancel')).toBe(true, 'Cancel button is not enabled'); + expect(await confirmDialog.isOkEnabled()).toBe(true, 'OK button is not enabled'); + expect(await confirmDialog.isCancelEnabled()).toBe(true, 'Cancel button is not enabled'); }); it('Cancel Leave library - [C290111]', async () => { - await page.goToMyLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.selectItem(sitePublic4Admin); - await toolbar.clickButton('Leave library'); + await toolbar.clickLeave(); await page.waitForDialog(); - expect(await confirmDialog.isButtonEnabled('Cancel')).toBe(true, 'Cancel button is not enabled'); - await confirmDialog.clickButton('Cancel'); - expect(await dataTable.getRowByName(sitePublic4Admin).isPresent()).toBe(true, `${sitePublic4Admin} was deleted`); + expect(await confirmDialog.isCancelEnabled()).toBe(true, 'Cancel button is not enabled'); + await confirmDialog.clickCancel(); + expect(await dataTable.isItemPresent(sitePublic4Admin)).toBe(true, `${sitePublic4Admin} was deleted`); }); it('Leave a library - failure notification - [C290107]', async () => { - await page.goToMyLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.selectItem(sitePublicUser); - await toolbar.clickButton('Leave library'); + await toolbar.clickLeave(); await page.waitForDialog(); - await confirmDialog.clickButton('OK'); - const text = await page.getSnackBarMessage(); + await confirmDialog.clickOk(); - expect(text).toEqual(`Cannot leave this library`); + expect(await page.getSnackBarMessage()).toEqual(`Cannot leave this library`); }); it('Cancel join - Favorite Libraries - [C290108]', async () => { - await page.goToFavoriteLibraries(); + await page.goToFavoriteLibrariesAndWait(); await dataTable.selectItem(siteModerated2Admin); await toolbar.clickButton('Cancel join request'); - const text = await page.getSnackBarMessage(); - expect(text).toEqual(`Canceled the request to join the library`); + expect(await page.getSnackBarMessage()).toEqual(`Canceled the request to join the library`); const hasJoinRequest = await apis.user.sites.hasMembershipRequest(siteModerated2Admin); expect(hasJoinRequest).toBe(false, `Join request exists on ${siteModerated2Admin}`); diff --git a/e2e/suites/actions/mark-favorite.test.ts b/e2e/suites/actions/mark-favorite.test.ts index 3f4afadcb2..9b517c4d9a 100644 --- a/e2e/suites/actions/mark-favorite.test.ts +++ b/e2e/suites/actions/mark-favorite.test.ts @@ -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 @@ -29,525 +29,454 @@ import { RepoClient } from '../../utilities/repo-client/repo-client'; import { Utils } from '../../utilities/utils'; describe('Mark items as favorites', () => { - const username = `user-${Utils.random()}`; + const username = `user-${Utils.random()}`; + + const parent = `parent-${Utils.random()}`; + + const fileNotFavUI = `fileNotFavUI-${Utils.random()}.txt`; + const fileFavUI = `fileFavUI-${Utils.random()}.txt`; + const fileNotFav1 = `fileNotFav1-${Utils.random()}.txt`; + const fileNotFav2 = `fileNotFav2-${Utils.random()}.txt`; + const fileNotFav3 = `fileNotFav3-${Utils.random()}.txt`; + const fileNotFav4 = `fileNotFav4-${Utils.random()}.txt`; + const fileFav1 = `fileFav1-${Utils.random()}.txt`; + const fileFav2 = `fileFav2-${Utils.random()}.txt`; + const fileFav3 = `fileFav3-${Utils.random()}.txt`; + const fileFav4 = `fileFav4-${Utils.random()}.txt`; + const folder = `folder-${Utils.random()}`; + + let fileNotFavUIId, fileFavUIId, fileNotFav1Id, fileNotFav2Id, fileNotFav3Id, fileNotFav4Id, fileFav1Id, fileFav2Id, fileFav3Id, fileFav4Id, folderId, parentId; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable, toolbar } = page; + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + + fileNotFavUIId = (await apis.user.nodes.createFile(fileNotFavUI, parentId)).entry.id; + fileFavUIId = (await apis.user.nodes.createFile(fileFavUI, parentId)).entry.id; + fileNotFav1Id = (await apis.user.nodes.createFile(fileNotFav1, parentId)).entry.id; + fileNotFav2Id = (await apis.user.nodes.createFile(fileNotFav2, parentId)).entry.id; + fileNotFav3Id = (await apis.user.nodes.createFile(fileNotFav3, parentId)).entry.id; + fileNotFav4Id = (await apis.user.nodes.createFile(fileNotFav4, parentId)).entry.id; + fileFav1Id = (await apis.user.nodes.createFile(fileFav1, parentId)).entry.id; + fileFav2Id = (await apis.user.nodes.createFile(fileFav2, parentId)).entry.id; + fileFav3Id = (await apis.user.nodes.createFile(fileFav3, parentId)).entry.id; + fileFav4Id = (await apis.user.nodes.createFile(fileFav4, parentId)).entry.id; + folderId = (await apis.user.nodes.createFolder(folder, parentId)).entry.id; + + await apis.user.favorites.addFavoritesByIds('file', [ fileFavUIId, fileFav1Id, fileFav2Id, fileFav3Id, fileFav4Id ]); + await apis.user.favorites.waitForApi({ expect: 5 }); + + await apis.user.shared.shareFilesByIds([ fileFav1Id, fileFav2Id, fileFav3Id, fileFav4Id ]); + await apis.user.shared.shareFilesByIds([ fileNotFav1Id, fileNotFav2Id, fileNotFav3Id, fileNotFav4Id ]); + await apis.user.shared.waitForApi({ expect: 8 }); + + await loginPage.loginWith(username); + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentId); + done(); + }); + + describe('on Personal Files', () => { + afterAll(async (done) => { + await apis.user.favorites.addFavoritesByIds('file', [ fileFavUIId, fileFav1Id, fileFav2Id, fileFav3Id, fileFav4Id ]); + await apis.user.favorites.addFavoriteById('folder', folderId); + await apis.user.favorites.removeFavoritesByIds([ fileNotFavUIId , fileNotFav1Id, fileNotFav2Id, fileNotFav3Id, fileNotFav4Id ]); + await apis.user.favorites.waitForApi({ expect: 6 }); + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parent); + done(); + }); + + it('Favorite action has empty star icon for an item not marked as favorite - [C217186]', async () => { + await dataTable.selectItem(fileNotFavUI); + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.getItemIconText('Favorite')).toEqual('star_border'); + }); + + it('Favorite action has empty star icon for multiple selection of items when some are not favorite - [C217187]', async () => { + await dataTable.selectMultipleItems([ fileNotFavUI, fileFavUI ]); + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.getItemIconText('Favorite')).toEqual('star_border'); + }); + + it('Favorite action has full star icon for items marked as favorite - [C217188]', async () => { + await dataTable.selectItem(fileFavUI); + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.getItemIconText('Remove favorite')).toEqual('star'); + }); + + it('favorite a file - [C217189]', async () => { + await dataTable.selectItem(fileNotFav1); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav1Id, { expect: true })).toBe(true, `${fileNotFav1} not marked as favorite`); + }); + + it('favorite a folder - [C280390]', async () => { + await dataTable.selectItem(folder); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(folderId, { expect: true })).toBe(true, `${folder} not marked as favorite`); + }); + + it('unfavorite an item - [C217190]', async () => { + await dataTable.selectItem(fileFav1); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav1Id, { expect: false })).toBe(false, `${fileFav1} is marked as favorite`); + }); + + it('favorite multiple items - all unfavorite - [C217192]', async () => { + await dataTable.selectMultipleItems([ fileNotFav2, fileNotFav3 ]); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav2Id, { expect: true })).toBe(true, `${fileNotFav2} not marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav3Id, { expect: true })).toBe(true, `${fileNotFav3} not marked as favorite`); + }); + + it('favorite multiple items - some favorite and some unfavorite - [C217194]', async () => { + await dataTable.selectMultipleItems([ fileNotFav4, fileFav2 ]); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav4Id, { expect: true })).toBe(true, `${fileNotFav4} not marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav2Id, { expect: true })).toBe(true, `${fileFav2} not marked as favorite`); + }); + + it('unfavorite multiple items - [C217193]', async () => { + await dataTable.selectMultipleItems([ fileFav3, fileFav4 ]) + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav3Id, { expect: false })).toBe(false, `${fileFav3} marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav4Id, { expect: false })).toBe(false, `${fileFav4} marked as favorite`); + }); + }); + + describe('on Recent Files', () => { + afterAll(async (done) => { + await apis.user.favorites.addFavoritesByIds('file', [ fileFav1Id, fileFav2Id, fileFav3Id, fileFav4Id ]); + await apis.user.favorites.removeFavoritesByIds([ fileNotFav1Id, fileNotFav2Id, fileNotFav3Id, fileNotFav4Id ]); + await apis.user.favorites.waitForApi({ expect: 6 }); + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.clickRecentFilesAndWait(); + done(); + }); + + it('favorite a file - [C280352]', async () => { + await dataTable.selectItem(fileNotFav1); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav1Id, { expect: true })).toBe(true, `${fileNotFav1} not marked as favorite`); + }); + + it('unfavorite an item - [C280353]', async () => { + await dataTable.selectItem(fileFav1); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav1Id, { expect: false })).toBe(false, `${fileFav1} is marked as favorite`); + }); + + it('favorite multiple items - all unfavorite - [C280355]', async () => { + await dataTable.selectMultipleItems([ fileNotFav2, fileNotFav3 ]); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav2Id, { expect: true })).toBe(true, `${fileNotFav2} not marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav3Id, { expect: true })).toBe(true, `${fileNotFav3} not marked as favorite`); + }); + + it('favorite multiple items - some favorite and some unfavorite - [C280357]', async () => { + await dataTable.selectMultipleItems([ fileNotFav4, fileFav2 ]); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav4Id, { expect: true })).toBe(true, `${fileNotFav4} not marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav2Id, { expect: true })).toBe(true, `${fileFav2} not marked as favorite`); + }); + + it('unfavorite multiple items - [C280356]', async () => { + await dataTable.selectMultipleItems([ fileFav3, fileFav4 ]); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav3Id, { expect: false })).toBe(false, `${fileFav3} marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav4Id, { expect: false })).toBe(false, `${fileFav4} marked as favorite`); + }); + }); + + describe('on Shared Files', () => { + afterAll(async (done) => { + await apis.user.favorites.addFavoritesByIds('file', [ fileFav1Id, fileFav2Id, fileFav3Id, fileFav4Id ]); + await apis.user.favorites.removeFavoritesByIds([ fileNotFav1Id, fileNotFav2Id, fileNotFav3Id, fileNotFav4Id ]); + await apis.user.favorites.waitForApi({ expect: 6 }); + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.clickSharedFilesAndWait(); + done(); + }); + + it('favorite a file - [C280362]', async () => { + await dataTable.selectItem(fileNotFav1); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav1Id, { expect: true })).toBe(true, `${fileNotFav1} not marked as favorite`); + }); - const file1NotFav = `file1-${Utils.random()}.txt`; - const file2NotFav = `file2-${Utils.random()}.txt`; - const file3Fav = `file3-${Utils.random()}.txt`; - const file4Fav = `file4-${Utils.random()}.txt`; - const folder1 = `folder-${Utils.random()}`; + it('unfavorite an item - [C280363]', async () => { + await dataTable.selectItem(fileFav1); + await toolbar.clickMoreActionsRemoveFavorite(); + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav1Id, { expect: false })).toBe(false, `${fileFav1} is marked as favorite`); + }); + + it('favorite multiple items - all unfavorite - [C280365]', async () => { + await dataTable.selectMultipleItems([ fileNotFav2, fileNotFav3 ]); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav2Id, { expect: true })).toBe(true, `${fileNotFav2} not marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav3Id, { expect: true })).toBe(true, `${fileNotFav3} not marked as favorite`); + }); + + it('favorite multiple items - some favorite and some unfavorite - [C280367]', async () => { + await dataTable.selectMultipleItems([ fileNotFav4, fileFav2 ]); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileNotFav4Id, { expect: true })).toBe(true, `${fileNotFav4} not marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav2Id, { expect: true })).toBe(true, `${fileFav2} not marked as favorite`); + }); + + it('unfavorite multiple items - [C280366]', async () => { + await dataTable.selectMultipleItems([ fileFav3, fileFav4 ]); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav3Id, { expect: false })).toBe(false, `${fileFav3} marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav4Id, { expect: false })).toBe(false, `${fileFav4} marked as favorite`); + }); + }); + + describe('on Favorites', () => { + afterAll(async (done) => { + await apis.user.favorites.addFavoritesByIds('file', [ fileFav1Id, fileFav2Id, fileFav3Id, fileFav4Id ]); + await apis.user.favorites.removeFavoritesByIds([ fileNotFav1Id, fileNotFav2Id, fileNotFav3Id, fileNotFav4Id ]); + await apis.user.favorites.waitForApi({ expect: 6 }); + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.refresh(); + await page.clickFavoritesAndWait(); + done(); + }); + + it('unfavorite an item - [C280368]', async () => { + await dataTable.selectItem(fileFav1); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav1Id, { expect: false })).toBe(false, `${fileFav1} is marked as favorite`); + expect(await dataTable.isItemPresent(fileFav1)).toBe(false, 'item still displayed'); + }); + + it('unfavorite multiple items - [C280374]', async () => { + await dataTable.selectMultipleItems([ fileFav3, fileFav4 ]); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav3Id, { expect: false })).toBe(false, `${fileFav3} marked as favorite`); + expect(await apis.user.favorites.isFavoriteWithRetry(fileFav4Id, { expect: false })).toBe(false, `${fileFav4} marked as favorite`); + expect(await dataTable.isItemPresent(fileFav3)).toBe(false, 'file3 still displayed'); + expect(await dataTable.isItemPresent(fileFav4)).toBe(false, 'file4 still displayed'); + }); + + it('Favorite action has full star icon for items marked as favorite - [C280371]', async () => { + await dataTable.selectItem(fileFav2); + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.getItemIconText('Remove favorite')).toEqual('star'); + }); + }); + + describe ('on File Libraries', () => { const siteName = `site-public-${Utils.random()}`; - const fileSiteNotFav1 = `file1-site-${Utils.random()}.txt`; - const fileSiteNotFav2 = `file2-site-${Utils.random()}.txt`; - const folderSite = `folder-site-${Utils.random()}`; - const fileSiteFav1 = `file3-${Utils.random()}.txt`; - const fileSiteFav2 = `file4-${Utils.random()}.txt`; - let file1Id, file2Id, file3Id, file4Id, folder1Id, fileSiteNotFav1Id, fileSiteNotFav2Id, folderSiteId, fileSiteFav1Id, fileSiteFav2Id; + const folderSite = `folderSite-${Utils.random()}`; - const apis = { - admin: new RepoClient(), - user: new RepoClient(username, username) - }; + const fileSiteNotFav1 = `fileSiteNotFav1-${Utils.random()}.txt`; + const fileSiteNotFav2 = `fileSiteNotFav2-${Utils.random()}.txt`; + const fileSiteNotFav3 = `fileSiteNotFav3-${Utils.random()}.txt`; + const fileSiteNotFav4 = `fileSiteNotFav4-${Utils.random()}.txt`; + const fileSiteFav1 = `fileSiteFav1-${Utils.random()}.txt`; + const fileSiteFav2 = `fileSiteFav2-${Utils.random()}.txt`; + const fileSiteFav3 = `fileSiteFav3-${Utils.random()}.txt`; + const fileSiteFav4 = `fileSiteFav4-${Utils.random()}.txt`; - const loginPage = new LoginPage(); - const page = new BrowsingPage(); - const { dataTable, toolbar } = page; + let folderSiteId, fileSiteNotFav1Id, fileSiteNotFav2Id, fileSiteNotFav3Id, fileSiteNotFav4Id; + let fileSiteFav1Id, fileSiteFav2Id, fileSiteFav3Id, fileSiteFav4Id; beforeAll(async (done) => { - await apis.admin.people.createUser({ username }); - file1Id = (await apis.user.nodes.createFile(file1NotFav)).entry.id; - file2Id = (await apis.user.nodes.createFile(file2NotFav)).entry.id; - file3Id = (await apis.user.nodes.createFile(file3Fav)).entry.id; - file4Id = (await apis.user.nodes.createFile(file4Fav)).entry.id; - folder1Id = (await apis.user.nodes.createFolder(folder1)).entry.id; + await apis.user.sites.createSite(siteName, SITE_VISIBILITY.PUBLIC); + const docLibId = await apis.user.sites.getDocLibId(siteName); + + folderSiteId = (await apis.user.nodes.createFolder(folderSite, docLibId)).entry.id; + fileSiteNotFav1Id = (await apis.user.nodes.createFile(fileSiteNotFav1, folderSiteId)).entry.id; + fileSiteNotFav2Id = (await apis.user.nodes.createFile(fileSiteNotFav2, folderSiteId)).entry.id; + fileSiteNotFav3Id = (await apis.user.nodes.createFile(fileSiteNotFav3, folderSiteId)).entry.id; + fileSiteNotFav4Id = (await apis.user.nodes.createFile(fileSiteNotFav4, folderSiteId)).entry.id; + fileSiteFav1Id = (await apis.user.nodes.createFile(fileSiteFav1, folderSiteId)).entry.id; + fileSiteFav2Id = (await apis.user.nodes.createFile(fileSiteFav2, folderSiteId)).entry.id; + fileSiteFav3Id = (await apis.user.nodes.createFile(fileSiteFav3, folderSiteId)).entry.id; + fileSiteFav4Id = (await apis.user.nodes.createFile(fileSiteFav4, folderSiteId)).entry.id; + + await apis.user.favorites.addFavoritesByIds('file', [ fileSiteFav1Id, fileSiteFav2Id, fileSiteFav3Id, fileSiteFav4Id ]); + + await apis.user.favorites.isFavoriteWithRetry(fileSiteFav1Id, { expect: true }); + await apis.user.favorites.isFavoriteWithRetry(fileSiteFav2Id, { expect: true }); + await apis.user.favorites.isFavoriteWithRetry(fileSiteFav3Id, { expect: true }); + await apis.user.favorites.isFavoriteWithRetry(fileSiteFav4Id, { expect: true }); + + done(); + }); + + afterAll(async (done) => { + await apis.user.sites.deleteSite(siteName); + done(); + }); - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.addFavoriteById('file', file4Id); + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.goToMyLibrariesAndWait(); + await page.dataTable.doubleClickOnRowByName(siteName); + await page.dataTable.waitForHeader(); + done(); + }); + + it('Favorite a folder - [C280391]', async () => { + await dataTable.selectItem(folderSite); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(folderSiteId, { expect: true })).toBe(true, `${folderSite} not marked as favorite`); + }); - await apis.user.shared.shareFilesByIds([ file1Id, file2Id, file3Id, file4Id ]); + it('Favorite a file - [C280342]', async () => { + await page.dataTable.doubleClickOnRowByName(folderSite); + await dataTable.selectItem(fileSiteNotFav1); + await toolbar.clickMoreActionsFavorite(); - await apis.user.sites.createSite(siteName, SITE_VISIBILITY.PUBLIC); - const docLibId = await apis.user.sites.getDocLibId(siteName); - folderSiteId = (await apis.user.nodes.createFolder(folderSite, docLibId)).entry.id; - fileSiteNotFav1Id = (await apis.user.nodes.createFile(fileSiteNotFav1, folderSiteId)).entry.id; - fileSiteFav1Id = (await apis.user.nodes.createFile(fileSiteFav1, folderSiteId)).entry.id; - fileSiteNotFav2Id = (await apis.user.nodes.createFile(fileSiteNotFav2, folderSiteId)).entry.id; - fileSiteFav2Id = (await apis.user.nodes.createFile(fileSiteFav2, folderSiteId)).entry.id; - await apis.user.favorites.addFavoriteById('file', fileSiteFav1Id); - await apis.user.favorites.addFavoriteById('file', fileSiteFav2Id); + expect(await apis.user.favorites.isFavoriteWithRetry(fileSiteNotFav1Id, { expect: true })).toBe(true, `${fileSiteNotFav1} not marked as favorite`); + }); + + it('Unfavorite an item - [C280343]', async () => { + await page.dataTable.doubleClickOnRowByName(folderSite); + await dataTable.selectItem(fileSiteFav1); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileSiteFav1Id, { expect: false })).toBe(false, `${fileSiteFav1} is marked as favorite`); + }); - await apis.user.favorites.waitForApi({ expect: 5 }); - await apis.user.search.waitForApi(username, { expect: 8 }); - await apis.user.shared.waitForApi({ expect: 4 }); + it('Favorite multiple items - all unfavorite - [C280345]', async () => { + await page.dataTable.doubleClickOnRowByName(folderSite); + await dataTable.selectMultipleItems([ fileSiteNotFav2, fileSiteNotFav3 ]); + await toolbar.clickMoreActionsFavorite(); - await loginPage.loginWith(username); - done(); + expect(await apis.user.favorites.isFavoriteWithRetry(fileSiteNotFav2Id, { expect: true })).toBe(true, 'item not marked as favorite'); + expect(await apis.user.favorites.isFavoriteWithRetry(fileSiteNotFav3Id, { expect: true })).toBe(true, 'item not marked as favorite'); + }); + + it('Unfavorite multiple items - [C280346]', async () => { + await page.dataTable.doubleClickOnRowByName(folderSite); + await dataTable.selectMultipleItems([ fileSiteFav2, fileSiteFav3 ]); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileSiteFav2Id, { expect: false })).toBe(false, 'item marked as favorite'); + expect(await apis.user.favorites.isFavoriteWithRetry(fileSiteFav3Id, { expect: false })).toBe(false, 'item marked as favorite'); + }); + + it('Favorite multiple items - some favorite and some unfavorite - [C280347]', async () => { + await page.dataTable.doubleClickOnRowByName(folderSite); + await dataTable.selectMultipleItems([ fileSiteNotFav4, fileSiteFav4 ]); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(fileSiteNotFav4Id, { expect: true })).toBe(true, 'item not marked as favorite'); + expect(await apis.user.favorites.isFavoriteWithRetry(fileSiteFav4Id, { expect: true })).toBe(true, 'item not marked as favorite'); + }); + }); + + describe('on a library', () => { + const adminSite1 = `adminSite1-${Utils.random()}`; + const adminSite2 = `adminSite2-${Utils.random()}`; + const adminSite3 = `adminSite3-${Utils.random()}`; + + beforeAll(async (done) => { + await apis.admin.sites.createSite(adminSite1); + await apis.admin.sites.createSite(adminSite2); + await apis.admin.sites.createSite(adminSite3); + await apis.admin.sites.addSiteMember(adminSite1, username, SITE_ROLES.SITE_CONSUMER.ROLE); + await apis.admin.sites.addSiteMember(adminSite2, username, SITE_ROLES.SITE_CONSUMER.ROLE); + await apis.admin.sites.addSiteMember(adminSite3, username, SITE_ROLES.SITE_CONSUMER.ROLE); + + await apis.user.favorites.addFavoriteById('site', adminSite2); + await apis.user.favorites.addFavoriteById('site', adminSite3); + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + done(); }); afterAll(async (done) => { - await Promise.all([ - apis.user.nodes.deleteNodesById([ file1Id, file2Id, file3Id, file4Id, folder1Id]), - apis.user.sites.deleteSite(siteName) - ]); - done(); - }); - - xit(''); - - describe('on Personal Files', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await page.clickPersonalFilesAndWait(); - done(); - }); - - it('Favorite action has empty star icon for an item not marked as favorite - [C217186]', async () => { - await dataTable.selectItem(file1NotFav); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.getItemIconText('Favorite')).toEqual('star_border'); - }); - - it('Favorite action has empty star icon for multiple selection of items when some are not favorite - [C217187]', async () => { - await dataTable.selectMultipleItems([ file1NotFav, file3Fav ]); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.getItemIconText('Favorite')).toEqual('star_border'); - }); - - it('Favorite action has full star icon for items marked as favorite - [C217188]', async () => { - await dataTable.selectItem(file3Fav); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.getItemIconText('Favorite')).toEqual('star'); - }); - - it('favorite a file - [C217189]', async () => { - await dataTable.selectItem(file1NotFav); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFavorite = await apis.user.favorites.isFavorite(file1Id); - expect(isFavorite).toBe(true, `${file1NotFav} not marked as favorite`); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('favorite a folder - [C280390]', async () => { - await dataTable.selectItem(folder1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFavorite = await apis.user.favorites.isFavorite(folder1Id); - expect(isFavorite).toBe(true, `${folder1} not marked as favorite`); - - await apis.user.favorites.removeFavoriteById(folder1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('unfavorite an item - [C217190]', async () => { - await dataTable.selectItem(file3Fav); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 4 }); - const isFavorite = await apis.user.favorites.isFavorite(file3Id); - expect(isFavorite).toBe(false, `${file3Fav} is marked as favorite`); - - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('favorite multiple items - all unfavorite - [C217192]', async () => { - await dataTable.selectMultipleItems([ file1NotFav, file2NotFav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 7 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file2Id); - expect(isFile1Fav).toBe(true, 'item not marked as favorite'); - expect(isFile2Fav).toBe(true, 'item not marked as favorite'); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.removeFavoriteById(file2Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('favorite multiple items - some favorite and some unfavorite - [C217194]', async () => { - await dataTable.selectMultipleItems([ file1NotFav, file3Fav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file3Id); - expect(isFile1Fav).toBe(true, 'item not marked as favorite'); - expect(isFile2Fav).toBe(true, 'item not marked as favorite'); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('unfavorite multiple items - [C217193]', async () => { - await dataTable.selectMultipleItems([ file3Fav, file4Fav ]) - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 3 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file3Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file4Id); - expect(isFile1Fav).toBe(false, 'item marked as favorite'); - expect(isFile2Fav).toBe(false, 'item marked as favorite'); - - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.addFavoriteById('file', file4Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - }); - - describe('on Recent Files', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await page.clickRecentFilesAndWait(); - done(); - }); - - it('favorite a file - [C280352]', async () => { - await dataTable.selectItem(file1NotFav); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFavorite = await apis.user.favorites.isFavorite(file1Id); - expect(isFavorite).toBe(true, `${file1NotFav} not marked as favorite`); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('unfavorite an item - [C280353]', async () => { - await dataTable.selectItem(file3Fav); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 4 }); - const isFavorite = await apis.user.favorites.isFavorite(file3Id); - expect(isFavorite).toBe(false, `${file3Fav} is marked as favorite`); - - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('favorite multiple items - all unfavorite - [C280355]', async () => { - await dataTable.selectMultipleItems([ file1NotFav, file2NotFav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 7 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file2Id); - expect(isFile1Fav).toBe(true, 'item not marked as favorite'); - expect(isFile2Fav).toBe(true, 'item not marked as favorite'); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.removeFavoriteById(file2Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('favorite multiple items - some favorite and some unfavorite - [C280357]', async () => { - await dataTable.selectMultipleItems([ file1NotFav, file3Fav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file3Id); - expect(isFile1Fav).toBe(true, 'item not marked as favorite'); - expect(isFile2Fav).toBe(true, 'item not marked as favorite'); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('unfavorite multiple items - [C280356]', async () => { - await dataTable.selectMultipleItems([ file3Fav, file4Fav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 3 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file3Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file4Id); - expect(isFile1Fav).toBe(false, 'item marked as favorite'); - expect(isFile2Fav).toBe(false, 'item marked as favorite'); - - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.addFavoriteById('file', file4Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - }); - - describe('on Shared Files', () => { - beforeAll(async (done) => { - await page.refresh(); - done(); - }); - - beforeEach(async (done) => { - await Utils.pressEscape(); - await page.clickSharedFilesAndWait(); - done(); - }); - - it('favorite a file - [C280362]', async () => { - await dataTable.selectItem(file1NotFav); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFavorite = await apis.user.favorites.isFavorite(file1Id); - expect(isFavorite).toBe(true, `${file1NotFav} not marked as favorite`); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('unfavorite an item - [C280363]', async () => { - await dataTable.selectItem(file3Fav); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 4 }); - const isFavorite = await apis.user.favorites.isFavorite(file3Id); - expect(isFavorite).toBe(false, `${file3Fav} is marked as favorite`); - - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('favorite multiple items - all unfavorite - [C280365]', async () => { - await dataTable.selectMultipleItems([ file1NotFav, file2NotFav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 7 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file2Id); - expect(isFile1Fav).toBe(true, 'item not marked as favorite'); - expect(isFile2Fav).toBe(true, 'item not marked as favorite'); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.removeFavoriteById(file2Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('favorite multiple items - some favorite and some unfavorite - [C280367]', async () => { - await dataTable.selectMultipleItems([ file1NotFav, file3Fav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file3Id); - expect(isFile1Fav).toBe(true, 'item not marked as favorite'); - expect(isFile2Fav).toBe(true, 'item not marked as favorite'); - - await apis.user.favorites.removeFavoriteById(file1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('unfavorite multiple items - [C280366]', async () => { - await dataTable.selectMultipleItems([ file3Fav, file4Fav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 3 }); - const isFile1Fav = await apis.user.favorites.isFavorite(file3Id); - const isFile2Fav = await apis.user.favorites.isFavorite(file4Id); - expect(isFile1Fav).toBe(false, 'item marked as favorite'); - expect(isFile2Fav).toBe(false, 'item marked as favorite'); - - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.addFavoriteById('file', file4Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - }); - - describe('on Favorites', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await page.refresh(); - await page.clickFavoritesAndWait(); - done(); - }); - - it('unfavorite an item - [C280368]', async () => { - await dataTable.selectItem(file3Fav); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 4 }); - const isFavorite = await apis.user.favorites.isFavorite(file3Id); - expect(isFavorite).toBe(false, 'item is marked as favorite'); - expect(await dataTable.getRowByName(file3Fav).isPresent()).toBe(false, 'item still displayed'); - - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('unfavorite multiple items - [C280374]', async () => { - await dataTable.selectMultipleItems([ file3Fav, file4Fav ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 3 }); - const isFavorite3 = await apis.user.favorites.isFavorite(file3Id); - const isFavorite4 = await apis.user.favorites.isFavorite(file4Id); - expect(isFavorite3).toBe(false, 'file3 marked as favorite'); - expect(isFavorite4).toBe(false, 'file4 marked as favorite'); - expect(await dataTable.getRowByName(file3Fav).isPresent()).toBe(false, 'file3 still displayed'); - expect(await dataTable.getRowByName(file4Fav).isPresent()).toBe(false, 'file4 still displayed'); - - await apis.user.favorites.addFavoriteById('file', file3Id); - await apis.user.favorites.addFavoriteById('file', file4Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('Favorite action has full star icon for items marked as favorite - [C280371]', async () => { - await dataTable.selectItem(file3Fav); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.getItemIconText('Favorite')).toEqual('star'); - }); - }); - - describe ('on File Libraries', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await page.clickFileLibrariesAndWait(); - await page.dataTable.doubleClickOnRowByName(siteName); - await page.dataTable.waitForHeader(); - done(); - }); - - it('Favorite a folder - [C280391]', async () => { - await dataTable.selectItem(folderSite); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFavorite = await apis.user.favorites.isFavorite(folderSiteId); - expect(isFavorite).toBe(true, `${folderSite} not marked as favorite`); - await apis.user.favorites.removeFavoriteById(folderSiteId); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('Favorite a file - [C280342]', async () => { - await page.dataTable.doubleClickOnRowByName(folderSite); - await dataTable.selectItem(fileSiteNotFav1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - const isFavorite = await apis.user.favorites.isFavorite(fileSiteNotFav1Id); - expect(isFavorite).toBe(true, `${fileSiteNotFav1} not marked as favorite`); - await apis.user.favorites.removeFavoriteById(fileSiteNotFav1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('Unfavorite an item - [C280343]', async () => { - await page.dataTable.doubleClickOnRowByName(folderSite); - await dataTable.selectItem(fileSiteFav1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 4 }); - const isFavorite = await apis.user.favorites.isFavorite(fileSiteFav1Id); - expect(isFavorite).toBe(false, `${fileSiteFav1} is marked as favorite`); - await apis.user.favorites.addFavoriteById('file', fileSiteFav1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('Favorite multiple items - all unfavorite - [C280345]', async () => { - await page.dataTable.doubleClickOnRowByName(folderSite); - await dataTable.selectMultipleItems([ fileSiteNotFav1, fileSiteNotFav2 ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 7 }); - - const isFile1Fav = await apis.user.favorites.isFavorite(fileSiteNotFav1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(fileSiteNotFav2Id); - expect(isFile1Fav).toBe(true, 'item not marked as favorite'); - expect(isFile2Fav).toBe(true, 'item not marked as favorite'); - await apis.user.favorites.removeFavoriteById(fileSiteNotFav1Id); - await apis.user.favorites.removeFavoriteById(fileSiteNotFav2Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('Unfavorite multiple items - [C280346]', async () => { - await page.dataTable.doubleClickOnRowByName(folderSite); - await dataTable.selectMultipleItems([ fileSiteFav1, fileSiteFav2 ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 3 }); - const isFile1Fav = await apis.user.favorites.isFavorite(fileSiteFav1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(fileSiteFav2Id); - expect(isFile1Fav).toBe(false, 'item marked as favorite'); - expect(isFile2Fav).toBe(false, 'item marked as favorite'); - await apis.user.favorites.addFavoriteById('file', fileSiteFav1Id); - await apis.user.favorites.addFavoriteById('file', fileSiteFav2Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - - it('Favorite multiple items - some favorite and some unfavorite - [C280347]', async () => { - await page.dataTable.doubleClickOnRowByName(folderSite); - await dataTable.selectMultipleItems([ fileSiteNotFav1, fileSiteFav1 ]); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - await apis.user.favorites.waitForApi({ expect: 6 }); - - const isFile1Fav = await apis.user.favorites.isFavorite(fileSiteNotFav1Id); - const isFile2Fav = await apis.user.favorites.isFavorite(fileSiteFav1); - expect(isFile1Fav).toBe(true, 'item not marked as favorite'); - expect(isFile2Fav).toBe(true, 'item not marked as favorite'); - await apis.user.favorites.removeFavoriteById(fileSiteNotFav1Id); - await apis.user.favorites.waitForApi({ expect: 5 }); - }); - }); - - describe('on a library', () => { - const adminSite1 = `adminSite1-${Utils.random()}`; - const adminSite2 = `adminSite2-${Utils.random()}`; - const adminSite3 = `adminSite3-${Utils.random()}`; - - beforeAll(async (done) => { - await apis.admin.sites.createSite(adminSite1); - await apis.admin.sites.createSite(adminSite2); - await apis.admin.sites.createSite(adminSite3); - await apis.admin.sites.addSiteMember(adminSite1, username, SITE_ROLES.SITE_CONSUMER.ROLE); - await apis.admin.sites.addSiteMember(adminSite2, username, SITE_ROLES.SITE_CONSUMER.ROLE); - await apis.admin.sites.addSiteMember(adminSite3, username, SITE_ROLES.SITE_CONSUMER.ROLE); - - await apis.user.favorites.addFavoriteById('site', adminSite2); - await apis.user.favorites.addFavoriteById('site', adminSite3); - done(); - }); - - beforeEach(async (done) => { - await Utils.pressEscape(); - done(); - }); - - afterAll(async (done) => { - await apis.admin.sites.deleteSite(adminSite1); - await apis.admin.sites.deleteSite(adminSite2); - await apis.admin.sites.deleteSite(adminSite3); - done(); - }); - - it('Mark a library as favorite - [C289974]', async () => { - await page.goToMyLibraries(); - await dataTable.selectItem(adminSite1); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - expect(await apis.user.favorites.isFavoriteWithRetry(adminSite1, { expect: true })).toBe(true, `${adminSite1} not favorite`); - }); - - it('Remove a library from favorites - on My Libraries - [C289975]', async () => { - await page.goToMyLibraries(); - await dataTable.selectItem(adminSite2); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - expect(await apis.user.favorites.isFavoriteWithRetry(adminSite2, { expect: false })).toBe(false, `${adminSite2} still favorite`); - }); - - it('Remove a library from favorites - on Favorite Libraries - [C289976]', async () => { - await page.goToFavoriteLibraries(); - await dataTable.selectItem(adminSite3); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); - expect(await dataTable.getRowByName(adminSite3).isPresent()).toBe(false, `${adminSite3} is displayed`); - expect(await apis.user.favorites.isFavoriteWithRetry(adminSite3, { expect: false })).toBe(false, `${adminSite3} still favorite`); - }); + await apis.admin.sites.deleteSite(adminSite1); + await apis.admin.sites.deleteSite(adminSite2); + await apis.admin.sites.deleteSite(adminSite3); + done(); + }); + + it('Mark a library as favorite - [C289974]', async () => { + await page.goToMyLibrariesAndWait(); + await dataTable.selectItem(adminSite1); + await toolbar.clickMoreActionsFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(adminSite1, { expect: true })).toBe(true, `${adminSite1} not favorite`); + }); + + it('Remove a library from favorites - on My Libraries - [C289975]', async () => { + await page.goToMyLibrariesAndWait(); + await dataTable.selectItem(adminSite2); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await apis.user.favorites.isFavoriteWithRetry(adminSite2, { expect: false })).toBe(false, `${adminSite2} still favorite`); + }); + + it('Remove a library from favorites - on Favorite Libraries - [C289976]', async () => { + await page.goToFavoriteLibrariesAndWait(); + await dataTable.selectItem(adminSite3); + await toolbar.clickMoreActionsRemoveFavorite(); + + expect(await dataTable.isItemPresent(adminSite3)).toBe(false, `${adminSite3} is displayed`); + expect(await apis.user.favorites.isFavoriteWithRetry(adminSite3, { expect: false })).toBe(false, `${adminSite3} still favorite`); }); + }); }); diff --git a/e2e/suites/actions/move.test.ts b/e2e/suites/actions/move.test.ts new file mode 100755 index 0000000000..70e4538b86 --- /dev/null +++ b/e2e/suites/actions/move.test.ts @@ -0,0 +1,714 @@ +/*! + * @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 . + */ + +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('Move content', () => { + const username = `user-${Utils.random()}`; + + const sourcePF = `sourcePersonal-${Utils.random()}`; let sourceIdPF; + const destinationPF = `destinationPersonal-${Utils.random()}`; let destinationIdPF; + + const sourceRF = `sourceRecent-${Utils.random()}`; let sourceIdRF; + const destinationRF = `destinationRecent-${Utils.random()}`; let destinationIdRF; + + const sourceSF = `sourceShared-${Utils.random()}`; let sourceIdSF; + const destinationSF = `destinationShared-${Utils.random()}`; let destinationIdSF; + + const sourceFav = `sourceFavorites-${Utils.random()}`; let sourceIdFav; + const destinationFav = `destinationFavorites-${Utils.random()}`; let destinationIdFav; + + const siteName = `site-${Utils.random()}`; + const folderSitePF = `folderSitePersonal-${Utils.random()}`; + const folderSiteRF = `folderSiteRecent-${Utils.random()}`; + const folderSiteSF = `folderSiteShared-${Utils.random()}`; + const folderSiteFav = `folderSiteFavorites-${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 moveDialog = new CopyMoveDialog(); + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + + 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); + + sourceIdPF = (await apis.user.nodes.createFolder(sourcePF)).entry.id; + destinationIdPF = (await apis.user.nodes.createFolder(destinationPF)).entry.id; + + sourceIdRF = (await apis.user.nodes.createFolder(sourceRF)).entry.id; + destinationIdRF = (await apis.user.nodes.createFolder(destinationRF)).entry.id; + + sourceIdSF = (await apis.user.nodes.createFolder(sourceSF)).entry.id; + destinationIdSF = (await apis.user.nodes.createFolder(destinationSF)).entry.id; + + sourceIdFav = (await apis.user.nodes.createFolder(sourceFav)).entry.id; + destinationIdFav = (await apis.user.nodes.createFolder(destinationFav)).entry.id; + + await loginPage.loginWith(username); + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(sourceIdPF); + await apis.user.nodes.deleteNodeById(sourceIdRF); + await apis.user.nodes.deleteNodeById(sourceIdSF); + await apis.user.nodes.deleteNodeById(sourceIdFav); + 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', () => { + const file1 = `file1-${Utils.random()}.txt`; + + const folder1 = `folder1-${Utils.random()}`; let folder1Id; + const fileInFolder = `fileInFolder-${Utils.random()}.txt`; + + const file2 = `file2-${Utils.random()}.txt`; + const file3 = `file3-${Utils.random()}.txt`; + + const file4 = `file4-${Utils.random()}.txt`; + const folder2 = `folder2-${Utils.random()}`; let folder2Id; + const fileInFolder2 = `fileInFolder2-${Utils.random()}.txt`; + + const existingFile = `existing-${Utils.random()}`; + + const existingFolder = `existing-${Utils.random()}`; + let existingId1, existingId2; + + const file2InFolder = `file2InFolder-${Utils.random()}.txt`; + const file3InFolder = `file3InFolder-${Utils.random()}.txt`; + + beforeAll(async (done) => { + await apis.user.nodes.createFile(file1, sourceIdPF); + + folder1Id = (await apis.user.nodes.createFolder(folder1, sourceIdPF)).entry.id; + await apis.user.nodes.createFile(fileInFolder, folder1Id); + + await apis.user.nodes.createFile(file2, sourceIdPF); + await apis.user.nodes.createFile(file3, sourceIdPF); + + await apis.user.nodes.createFile(`${existingFile}.txt`, sourceIdPF); + await apis.user.nodes.createFile(`${existingFile}.txt`, destinationIdPF); + + existingId1 = (await apis.user.nodes.createFolder(existingFolder, sourceIdPF)).entry.id; + existingId2 = (await apis.user.nodes.createFolder(existingFolder, destinationIdPF)).entry.id; + await apis.user.nodes.createFile(file2InFolder, existingId1); + await apis.user.nodes.createFile(file3InFolder, existingId2); + + await apis.user.nodes.createFile(file4, sourceIdPF); + folder2Id = (await apis.user.nodes.createFolder(folder2, sourceIdPF)).entry.id; + await apis.user.nodes.createFile(fileInFolder2, folder2Id); + + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(sourcePF); + done(); + }); + + it('Move a file - [C217316]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationPF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file1)).toBe(false, `${file1} still 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('Move a folder with content - [C217317]', async () => { + await dataTable.selectItem(folder1); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationPF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(folder1)).toBe(false, `${folder1} still 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 folder`); + + await dataTable.doubleClickOnRowByName(folder1); + expect(await dataTable.isItemPresent(fileInFolder)).toBe(true, `${fileInFolder} is not present in parent folder`); + }); + + it('Move multiple items - [C291958]', async () => { + await dataTable.selectMultipleItems([file2, file3]); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationPF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 2 items'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file2)).toBe(false, `${file2} still present in source folder`); + expect(await dataTable.isItemPresent(file3)).toBe(false, `${file3} still 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('Move a file with a name that already exists on the destination - [C217318]', async () => { + await dataTable.selectItem(existingFile); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationPF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Move unsuccessful, a file with the same name already exists'); + expect(msg).not.toContain('Undo'); + + await moveDialog.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(false, `${existingFile}-1.txt is present in destination folder`); + }); + + it('Move a folder with a name that already exists on the destination - [C217319]', async () => { + await dataTable.selectItem(existingFolder); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationPF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(existingFolder)).toBe(false, `${existingFolder} still 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('Move items into a library - [C291969]', async () => { + await dataTable.selectMultipleItems([file4, folder2]); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('File Libraries'); + await moveDialog.doubleClickOnRow(siteName); + await moveDialog.doubleClickOnRow('documentLibrary'); + await moveDialog.selectDestination(folderSitePF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 2 items'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file4)).toBe(false, `${file4} still present in source folder`); + expect(await dataTable.isItemPresent(folder2)).toBe(false, `${folder2} still present in source folder`); + + await page.goToMyLibraries(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.doubleClickOnRowByName(folderSitePF); + + expect(await dataTable.isItemPresent(file4)).toBe(true, `${file4} not present in destination folder`); + expect(await dataTable.isItemPresent(folder2)).toBe(true, `${folder2} not present in destination folder`); + await dataTable.doubleClickOnRowByName(folder2); + expect(await dataTable.isItemPresent(fileInFolder2)).toBe(true, `${fileInFolder2} not present in parent folder`); + }); + }); + + describe('from Recent Files', () => { + const file1 = `file1-${Utils.random()}.txt`; + + const file2 = `file2-${Utils.random()}.txt`; + const file3 = `file3-${Utils.random()}.txt`; + + const file4 = `file4-${Utils.random()}.txt`; + + const existingFile = `existing-${Utils.random()}`; + + beforeAll(async (done) => { + await apis.user.nodes.createFile(file1, sourceIdRF); + + await apis.user.nodes.createFile(file2, sourceIdRF); + await apis.user.nodes.createFile(file3, sourceIdRF); + + await apis.user.nodes.createFile(`${existingFile}.txt`, sourceIdRF); + await apis.user.nodes.createFile(`${existingFile}.txt`, destinationIdRF); + + await apis.user.nodes.createFile(file4, sourceIdRF); + + await apis.user.search.waitForApi(username, { expect: 16 }); + + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.clickRecentFilesAndWait(); + done(); + }); + + it('Move a file - [C280230]', async () => { + await dataTable.selectItem(file1, sourceRF); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationRF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file1, destinationRF)).toBe(true, `${file1} from ${destinationRF} not present`); + expect(await dataTable.isItemPresent(file1, sourceRF)).toBe(false, `${file1} from ${sourceRF} is present`); + + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(destinationRF); + expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`); + }); + + it('Move multiple items - [C280237]', async () => { + await dataTable.selectMultipleItems([file2, file3], sourceRF); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationRF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 2 items'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file2, destinationRF)).toBe(true, `${file2} from ${destinationRF} not present`); + expect(await dataTable.isItemPresent(file3, destinationRF)).toBe(true, `${file3} from ${destinationRF} not present`); + expect(await dataTable.isItemPresent(file2, sourceRF)).toBe(false, `${file2} from ${sourceRF} is present`); + expect(await dataTable.isItemPresent(file3, sourceRF)).toBe(false, `${file3} from ${sourceRF} is present`); + + 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('Move a file with a name that already exists on the destination - [C291970]', async () => { + await dataTable.selectItem(existingFile, sourceRF); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationRF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Move unsuccessful, a file with the same name already exists'); + expect(msg).not.toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(existingFile, sourceRF)).toBe(true, `${existingFile} from ${sourceRF} not present`); + expect(await dataTable.isItemPresent(existingFile, destinationRF)).toBe(true, `${existingFile} from ${destinationRF} not present`); + + 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(false, `${existingFile}-1.txt is present in destination folder`); + }); + + it('Move items into a library - [C291971]', async () => { + await dataTable.selectItem(file4, sourceRF); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('File Libraries'); + await moveDialog.doubleClickOnRow(siteName); + await moveDialog.doubleClickOnRow('documentLibrary'); + await moveDialog.selectDestination(folderSiteRF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file4, folderSiteRF)).toBe(true, `${file4} from ${folderSiteRF} not present`); + expect(await dataTable.isItemPresent(file4, sourceRF)).toBe(false, `${file4} from ${sourceRF} is present`); + + await page.goToMyLibraries(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.doubleClickOnRowByName(folderSiteRF); + + expect(await dataTable.isItemPresent(file4)).toBe(true, `${file4} not present in destination folder`); + }); + }); + + describe('from Shared Files', () => { + const file1 = `file1-${Utils.random()}.txt`; let file1Id; + + const file2 = `file2-${Utils.random()}.txt`; let file2Id; + const file3 = `file3-${Utils.random()}.txt`; let file3Id; + + const file4 = `file4-${Utils.random()}.txt`; let file4Id; + + const existingFile = `existing-${Utils.random()}`; let existingFileId; + + beforeAll(async (done) => { + file1Id = (await apis.user.nodes.createFile(file1, sourceIdSF)).entry.id; + await apis.user.shared.shareFileById(file1Id); + + file2Id = (await apis.user.nodes.createFile(file2, sourceIdSF)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, sourceIdSF)).entry.id; + await apis.user.shared.shareFileById(file2Id); + await apis.user.shared.shareFileById(file3Id); + + existingFileId = (await apis.user.nodes.createFile(`${existingFile}.txt`, sourceIdSF)).entry.id; + await apis.user.shared.shareFileById(existingFileId); + await apis.user.nodes.createFile(`${existingFile}.txt`, destinationIdSF); + + file4Id = (await apis.user.nodes.createFile(file4, sourceIdSF)).entry.id; + await apis.user.shared.shareFileById(file4Id); + + await apis.user.shared.waitForApi({ expect: 5 }); + + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.clickSharedFilesAndWait(); + done(); + }); + + it('Move a file - [C280243]', async () => { + await dataTable.selectItem(file1, sourceSF); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationSF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file1, destinationSF)).toBe(true, `${file1} from ${destinationSF} not present`); + expect(await dataTable.isItemPresent(file1, sourceSF)).toBe(false, `${file1} from ${sourceSF} is present`); + + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(destinationSF); + expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`); + }); + + it('Move multiple items - [C280250]', async () => { + await dataTable.selectMultipleItems([file2, file3], sourceSF); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationSF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 2 items'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file2, destinationSF)).toBe(true, `${file2} from ${destinationSF} not present`); + expect(await dataTable.isItemPresent(file3, destinationSF)).toBe(true, `${file3} from ${destinationSF} not present`); + expect(await dataTable.isItemPresent(file2, sourceSF)).toBe(false, `${file2} from ${sourceSF} is present`); + expect(await dataTable.isItemPresent(file3, sourceSF)).toBe(false, `${file3} from ${sourceSF} is present`); + + 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('Move a file with a name that already exists on the destination - [C291977]', async () => { + await dataTable.selectItem(existingFile, sourceSF); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationSF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Move unsuccessful, a file with the same name already exists'); + expect(msg).not.toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(existingFile, sourceSF)).toBe(true, `${existingFile} from ${sourceSF} not present`); + expect(await dataTable.isItemPresent(existingFile, destinationSF)).toBe(false, `${existingFile} from ${destinationSF} is present`); + + 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(false, `${existingFile}-1.txt not present in destination folder`); + }); + + it('Move items into a library - [C291978]', async () => { + await dataTable.selectItem(file4, sourceSF); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('File Libraries'); + await moveDialog.doubleClickOnRow(siteName); + await moveDialog.doubleClickOnRow('documentLibrary'); + await moveDialog.selectDestination(folderSiteSF); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file4, folderSiteSF)).toBe(true, `${file4} from ${folderSiteSF} not present`); + expect(await dataTable.isItemPresent(file4, sourceSF)).toBe(false, `${file4} from ${sourceSF} is present`); + + await page.goToMyLibraries(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.doubleClickOnRowByName(folderSiteSF); + + expect(await dataTable.isItemPresent(file4)).toBe(true, `${file4} not present in destination folder`); + }); + }); + + describe('from Favorites', () => { + 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 file4 = `file4-${Utils.random()}.txt`; let file4Id; + const folder2 = `folder2-${Utils.random()}`; let folder2Id; + const fileInFolder2 = `fileInFolder2-${Utils.random()}.txt`; + + const existingFile = `existing-${Utils.random()}`; let existingFileId; + + const existingFolder = `existing-${Utils.random()}`; + let existingId1, existingId2; + const file2InFolder = `file2InFolder-${Utils.random()}.txt`; + const file3InFolder = `file3InFolder-${Utils.random()}.txt`; + + beforeAll(async (done) => { + file1Id = (await apis.user.nodes.createFile(file1, sourceIdFav)).entry.id; + await apis.user.favorites.addFavoriteById('file', file1Id); + + folder1Id = (await apis.user.nodes.createFolder(folder1, sourceIdFav)).entry.id; + await apis.user.nodes.createFile(fileInFolder, folder1Id); + await apis.user.favorites.addFavoriteById('folder', folder1Id); + + file2Id = (await apis.user.nodes.createFile(file2, sourceIdFav)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, sourceIdFav)).entry.id; + await apis.user.favorites.addFavoriteById('file', file2Id); + await apis.user.favorites.addFavoriteById('file', file3Id); + + existingFileId = (await apis.user.nodes.createFile(`${existingFile}.txt`, sourceIdFav)).entry.id; + await apis.user.favorites.addFavoriteById('file', existingFileId); + await apis.user.nodes.createFile(`${existingFile}.txt`, destinationIdFav); + + existingId1 = (await apis.user.nodes.createFolder(existingFolder, sourceIdFav)).entry.id; + existingId2 = (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.favorites.addFavoriteById('folder', existingId1); + + file4Id = (await apis.user.nodes.createFile(file4, sourceIdFav)).entry.id; + folder2Id = (await apis.user.nodes.createFolder(folder2, sourceIdFav)).entry.id; + await apis.user.nodes.createFile(fileInFolder2, folder2Id); + await apis.user.favorites.addFavoriteById('file', file4Id); + await apis.user.favorites.addFavoriteById('folder', folder2Id); + + await apis.user.favorites.waitForApi({ expect: 9 }); + + done(); + }); + + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.clickFavoritesAndWait(); + done(); + }); + + it('Move a file - [C280256]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationFav); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file1, destinationFav)).toBe(true, `${file1} from ${destinationFav} not present`); + expect(await dataTable.isItemPresent(file1, sourceFav)).toBe(false, `${file1} from ${sourceFav} is present`); + + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(destinationFav); + expect(await dataTable.isItemPresent(file1)).toBe(true, `${file1} not present in destination folder`); + }); + + it('Move a folder with content - [C280257]', async () => { + await dataTable.selectItem(folder1); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationFav); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(folder1, sourceFav)).toBe(false, `${folder1} from ${sourceFav} is present`); + expect(await dataTable.isItemPresent(folder1, destinationFav)).toBe(true, `${folder1} from ${destinationFav} not present`); + + 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('Move multiple items - [C280258]', async () => { + await dataTable.selectMultipleItems([file2, file3]); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationFav); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 2 items'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file2, destinationFav)).toBe(true, `${file2} from ${destinationFav} not present`); + expect(await dataTable.isItemPresent(file3, destinationFav)).toBe(true, `${file3} from ${destinationFav} not present`); + expect(await dataTable.isItemPresent(file2, sourceFav)).toBe(false, `${file2} from ${sourceFav} is present`); + expect(await dataTable.isItemPresent(file3, sourceFav)).toBe(false, `${file3} from ${sourceFav} is present`); + + 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('Move a file with a name that already exists on the destination - [C280263]', async () => { + await dataTable.selectItem(existingFile); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationFav); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Move unsuccessful, a file with the same name already exists'); + expect(msg).not.toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(existingFile, sourceFav)).toBe(true, `${existingFile} from ${sourceFav} not present`); + expect(await dataTable.isItemPresent(existingFile, destinationFav)).toBe(false, `${existingFile} from ${destinationFav} is present`); + + 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(false, `${existingFile}-1.txt is present in destination folder`); + }); + + it('Move a folder with a name that already exists on the destination - [C280259]', async () => { + await dataTable.selectItem(existingFolder); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('Personal Files'); + await moveDialog.selectDestination(destinationFav); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 1 item'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(existingFolder, sourceFav)).toBe(false, `${existingFolder} from ${sourceFav} is present`); + // expect(await dataTable.isItemPresent(existingFolder, destinationFav)).toBe(true, `${existingFolder} from ${destinationFav} not present`); + + 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('Move items into a library - [C291979]', async () => { + await dataTable.selectMultipleItems([file4, folder2], sourceFav); + await toolbar.clickMoreActionsMove(); + await moveDialog.selectLocation('File Libraries'); + await moveDialog.doubleClickOnRow(siteName); + await moveDialog.doubleClickOnRow('documentLibrary'); + await moveDialog.selectDestination(folderSiteFav); + await moveDialog.clickMove(); + const msg = await page.getSnackBarMessage(); + expect(msg).toContain('Moved 2 items'); + expect(msg).toContain('Undo'); + + await moveDialog.waitForDialogToClose(); + expect(await dataTable.isItemPresent(file4, folderSiteFav)).toBe(true, `${file4} from ${folderSiteFav} not present`); + expect(await dataTable.isItemPresent(file4, sourceFav)).toBe(false, `${file4} from ${sourceFav} is present`); + expect(await dataTable.isItemPresent(folder2, folderSiteFav)).toBe(true, `${folder2} from ${folderSiteFav} not present`); + expect(await dataTable.isItemPresent(folder2, sourceFav)).toBe(false, `${folder2} from ${sourceFav} is present`); + + await page.goToMyLibraries(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.doubleClickOnRowByName(folderSiteFav); + + expect(await dataTable.isItemPresent(file4)).toBe(true, `${file4} not present in destination folder`); + expect(await dataTable.isItemPresent(folder2)).toBe(true, `${folder2} not present in destination folder`); + await dataTable.doubleClickOnRowByName(folder2); + expect(await dataTable.isItemPresent(fileInFolder2)).toBe(true, `${fileInFolder2} not present in parent folder`); + }); + }); + +}); diff --git a/e2e/suites/actions/new-menu.test.ts b/e2e/suites/actions/new-menu.test.ts index 5ea766fe42..79e1b2395d 100755 --- a/e2e/suites/actions/new-menu.test.ts +++ b/e2e/suites/actions/new-menu.test.ts @@ -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 @@ -70,88 +70,79 @@ describe('New menu', () => { await page.clickPersonalFiles(); await sidenav.openNewMenu(); - expect(await sidenav.menu.isMenuItemPresent('Create folder')).toBe(true, 'Create Folder option not present'); - expect(await sidenav.menu.isMenuItemPresent('Create Library')).toBe(true, 'Create Library option not present'); - expect(await sidenav.menu.isMenuItemPresent('Upload file')).toBe(true, 'Upload File option not present'); - expect(await sidenav.menu.isMenuItemPresent('Upload folder')).toBe(true, 'Upload Folder option not present'); + expect(await sidenav.menu.isCreateFolderPresent()).toBe(true, 'Create Folder option not present'); + expect(await sidenav.menu.isCreateLibraryPresent()).toBe(true, 'Create Library option not present'); + expect(await sidenav.menu.isUploadFilePresent()).toBe(true, 'Upload File option not present'); + expect(await sidenav.menu.isUploadFolderPresent()).toBe(true, 'Upload Folder option not present'); - expect(await sidenav.menu.getItemByLabel('Create Library').isEnabled()).toBe(true, 'Create Library is not enabled'); + expect(await sidenav.menu.isCreateLibraryEnabled()).toBe(true, 'Create Library is not enabled'); }); it('Create folder is enabled when having enough permissions - Personal Files - [C216339]', async () => { await page.clickPersonalFiles(); await page.sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Create folder').isEnabled(); - expect(isEnabled).toBe(true, 'Create folder is not enabled'); + expect(await sidenav.menu.isCreateFolderEnabled()).toBe(true, 'Create folder is not enabled'); }); it('Create folder is enabled when having enough permissions - File Libraries - [C280393]', async () => { - await page.clickFileLibraries(); + await page.goToMyLibrariesAndWait(); await page.dataTable.doubleClickOnRowByName(siteUser); await page.sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Create folder').isEnabled(); - expect(isEnabled).toBe(true, 'Create folder is not enabled'); + expect(await sidenav.menu.isCreateFolderEnabled()).toBe(true, 'Create folder is not enabled'); }); it('Create folder is disabled when not enough permissions - [C280397]', async () => { - await page.clickFileLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteAdmin); await sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Create folder').isEnabled(); - expect(isEnabled).toBe(false, 'Create folder is not disabled'); + expect(await sidenav.menu.isCreateFolderEnabled()).toBe(false, 'Create folder is not disabled'); }); it('Upload File option is enabled when having enough permissions - on Personal Files - [C217145]', async () => { await page.clickPersonalFiles(); await sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Upload file').isEnabled(); - expect(isEnabled).toBe(true, 'Upload file is not enabled in Personal Files'); + expect(await sidenav.menu.isUploadFileEnabled()).toBe(true, 'Upload file is not enabled in Personal Files'); }); it('Upload File option is enabled when having permissions - on File Libraries - [C290142]', async () => { - await page.clickFileLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteUser); await sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Upload file').isEnabled(); - expect(isEnabled).toBe(true, 'Upload file is not enabled in File Libraries'); + expect(await sidenav.menu.isUploadFileEnabled()).toBe(true, 'Upload file is not enabled in File Libraries'); }); it('Upload File option is disabled when user cannot create content in that location - [C217146]', async () => { - await page.clickFileLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteAdmin); await sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Upload file').isEnabled(); - expect(isEnabled).toBe(false, 'Upload file is not disabled'); + expect(await sidenav.menu.isUploadFileEnabled()).toBe(false, 'Upload file is not disabled'); }); it('Upload Folder option is enabled when having enough permissions - on Personal Files - [C213196]', async () => { await page.clickPersonalFiles(); await sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Upload folder').isEnabled(); - expect(isEnabled).toBe(true, 'Upload folder is not enabled in Personal Files'); + expect(await sidenav.menu.isUploadFolderEnabled()).toBe(true, 'Upload folder is not enabled in Personal Files'); }); it('Upload Folder option is enabled when having permissions - on File Libraries - [C290146]', async () => { - await page.clickFileLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteUser); await sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Upload folder').isEnabled(); - expect(isEnabled).toBe(true, 'Upload folder is not enabled in File Libraries'); + expect(await sidenav.menu.isUploadFolderEnabled()).toBe(true, 'Upload folder is not enabled in File Libraries'); }); it('Upload Folder option is disabled when user cannot create content in that location - [C213193]', async () => { - await page.clickFileLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteAdmin); await sidenav.openNewMenu(); - const isEnabled = await sidenav.menu.getItemByLabel('Upload folder').isEnabled(); - expect(isEnabled).toBe(false, 'Upload folder is not disabled'); + expect(await sidenav.menu.isUploadFolderEnabled()).toBe(false, 'Upload folder is not disabled'); }); it('Create folder enabled button tooltip - [C216342]', async () => { @@ -163,7 +154,7 @@ describe('New menu', () => { }); it('Create folder disabled button tooltip - [C280398]', async () => { - await page.clickFileLibraries(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteAdmin); await sidenav.openNewMenu(); diff --git a/e2e/suites/actions/permanently-delete.test.ts b/e2e/suites/actions/permanently-delete.test.ts index 68427f3af6..d028fc2ad2 100755 --- a/e2e/suites/actions/permanently-delete.test.ts +++ b/e2e/suites/actions/permanently-delete.test.ts @@ -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 @@ -79,59 +79,55 @@ describe('Permanently delete from Trash', () => { it('delete a file - [C217091]', async () => { await dataTable.selectItem(file1); - await toolbar.getButtonByTitleAttribute('Permanently delete').click(); + await toolbar.clickPermanentlyDelete(); await page.waitForDialog(); - await confirmDialog.clickButton('Delete'); - const text = await page.getSnackBarMessage(); + await confirmDialog.clickDelete(); - expect(text).toEqual(`${file1} deleted`); - expect(await dataTable.getRowByName(file1).isPresent()).toBe(false, 'Item was not deleted'); + expect(await page.getSnackBarMessage()).toEqual(`${file1} deleted`); + expect(await dataTable.isItemPresent(file1)).toBe(false, 'Item was not deleted'); }); it('delete a folder - [C280416]', async () => { await dataTable.selectItem(folder1); - await toolbar.getButtonByTitleAttribute('Permanently delete').click(); + await toolbar.clickPermanentlyDelete(); await page.waitForDialog(); - await confirmDialog.clickButton('Delete'); - const text = await page.getSnackBarMessage(); + await confirmDialog.clickDelete(); - expect(text).toEqual(`${folder1} deleted`); - expect(await dataTable.getRowByName(folder1).isPresent()).toBe(false, 'Item was not deleted'); + expect(await page.getSnackBarMessage()).toEqual(`${folder1} deleted`); + expect(await dataTable.isItemPresent(folder1)).toBe(false, 'Item was not deleted'); }); it('delete a library - [C290103]', async () => { await dataTable.selectItem(site); - await toolbar.getButtonByTitleAttribute('Permanently delete').click(); + await toolbar.clickPermanentlyDelete(); await page.waitForDialog(); - await confirmDialog.clickButton('Delete'); - const text = await page.getSnackBarMessage(); + await confirmDialog.clickDelete(); - expect(text).toEqual(`${site} deleted`); - expect(await dataTable.getRowByName(site).isPresent()).toBe(false, `${site} was not deleted`); + expect(await page.getSnackBarMessage()).toEqual(`${site} deleted`); + expect(await dataTable.isItemPresent(site)).toBe(false, `${site} was not deleted`); }); it('delete multiple items - [C280417]', async () => { await dataTable.selectMultipleItems([ file2, folder2 ]); - await toolbar.getButtonByTitleAttribute('Permanently delete').click(); + await toolbar.clickPermanentlyDelete(); await page.waitForDialog(); - await confirmDialog.clickButton('Delete'); - const text = await page.getSnackBarMessage(); + await confirmDialog.clickDelete(); - expect(text).toEqual(`2 items deleted`); - expect(await dataTable.getRowByName(file2).isPresent()).toBe(false, 'Item was not deleted'); - expect(await dataTable.getRowByName(folder2).isPresent()).toBe(false, 'Item was not deleted'); + expect(await page.getSnackBarMessage()).toEqual(`2 items deleted`); + expect(await dataTable.isItemPresent(file2)).toBe(false, 'Item was not deleted'); + expect(await dataTable.isItemPresent(folder2)).toBe(false, 'Item was not deleted'); }); it('Confirmation dialog UI - [C269113]', async () => { await dataTable.selectItem(file3); - await toolbar.getButtonByTitleAttribute('Permanently delete').click(); + await toolbar.clickPermanentlyDelete(); await page.waitForDialog(); expect(await confirmDialog.isDialogOpen()).toBe(true, 'Confirm delete dialog not open'); expect(await confirmDialog.getTitle()).toContain('Delete from trash'); expect(await confirmDialog.getText()).toContain('This will permanently remove the selected item(s)'); - expect(await confirmDialog.isButtonEnabled('Delete')).toBe(true, 'DELETE button is not enabled'); - expect(await confirmDialog.isButtonEnabled('Keep')).toBe(true, 'KEEP button is not enabled'); + expect(await confirmDialog.isDeleteEnabled()).toBe(true, 'DELETE button is not enabled'); + expect(await confirmDialog.isKeepEnabled()).toBe(true, 'KEEP button is not enabled'); await Utils.pressEscape(); await dataTable.clearSelection(); @@ -139,11 +135,11 @@ describe('Permanently delete from Trash', () => { it('Keep action cancels the deletion - [C269115]', async () => { await dataTable.selectItem(file3); - await toolbar.getButtonByTitleAttribute('Permanently delete').click(); + await toolbar.clickPermanentlyDelete(); await page.waitForDialog(); - expect(await confirmDialog.isButtonEnabled('Keep')).toBe(true, 'KEEP button is not enabled'); - await confirmDialog.clickButton('Keep'); - expect(await dataTable.getRowByName(file3).isPresent()).toBe(true, 'Item was deleted'); + expect(await confirmDialog.isKeepEnabled()).toBe(true, 'KEEP button is not enabled'); + await confirmDialog.clickKeep(); + expect(await dataTable.isItemPresent(file3)).toBe(true, 'Item was deleted'); }); }); diff --git a/e2e/suites/actions/restore.test.ts b/e2e/suites/actions/restore.test.ts index 7d4499c192..d5783f7693 100755 --- a/e2e/suites/actions/restore.test.ts +++ b/e2e/suites/actions/restore.test.ts @@ -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 @@ -52,8 +52,6 @@ describe('Restore from Trash', () => { done(); }); - xit(''); - describe('successful restore', () => { const file = `file-${Utils.random()}.txt`; let fileId; const folder = `folder-${Utils.random()}`; let folderId; @@ -81,59 +79,59 @@ describe('Restore from Trash', () => { it('restore file - [C217177]', async () => { await dataTable.selectItem(file); - await toolbar.getButtonByTitleAttribute('Restore').click(); + await toolbar.clickRestore(); const text = await page.getSnackBarMessage(); expect(text).toContain(`${file} restored`); expect(text).toContain(`View`); - expect(await dataTable.getRowByName(file).isPresent()).toBe(false, 'Item was not removed from list'); + expect(await dataTable.isItemPresent(file)).toBe(false, 'Item was not removed from list'); await page.clickPersonalFilesAndWait(); - expect(await page.dataTable.getRowByName(file).isPresent()).toBe(true, 'Item not displayed in list'); + expect(await page.dataTable.isItemPresent(file)).toBe(true, 'Item not displayed in list'); await apis.user.nodes.deleteNodeById(fileId, false); }); it('restore folder - [C280438]', async () => { await dataTable.selectItem(folder); - await toolbar.getButtonByTitleAttribute('Restore').click(); + await toolbar.clickRestore(); const text = await page.getSnackBarMessage(); expect(text).toContain(`${folder} restored`); expect(text).toContain(`View`); - expect(await dataTable.getRowByName(folder).isPresent()).toBe(false, 'Item was not removed from list'); + expect(await dataTable.isItemPresent(folder)).toBe(false, 'Item was not removed from list'); await page.clickPersonalFilesAndWait(); - expect(await page.dataTable.getRowByName(folder).isPresent()).toBe(true, 'Item not displayed in list'); + expect(await page.dataTable.isItemPresent(folder)).toBe(true, 'Item not displayed in list'); await apis.user.nodes.deleteNodeById(folderId, false); }); it('restore library - [C290104]', async () => { await dataTable.selectItem(site); - await toolbar.getButtonByTitleAttribute('Restore').click(); + await toolbar.clickRestore(); const text = await page.getSnackBarMessage(); expect(text).toContain(`${site} restored`); expect(text).toContain(`View`); - expect(await dataTable.getRowByName(site).isPresent()).toBe(false, `${site} was not removed from list`); + expect(await dataTable.isItemPresent(site)).toBe(false, `${site} was not removed from list`); await page.clickFileLibrariesAndWait(); - expect(await page.dataTable.getRowByName(site).isPresent()).toBe(true, `${site} not displayed in list`); + expect(await page.dataTable.isItemPresent(site)).toBe(true, `${site} not displayed in list`); }); it('restore multiple items - [C217182]', async () => { await dataTable.selectMultipleItems([file, folder]); - await toolbar.getButtonByTitleAttribute('Restore').click(); + await toolbar.clickRestore(); const text = await page.getSnackBarMessage(); expect(text).toContain(`Restore successful`); expect(text).not.toContain(`View`); - expect(await dataTable.getRowByName(file).isPresent()).toBe(false, 'Item was not removed from list'); - expect(await dataTable.getRowByName(folder).isPresent()).toBe(false, 'Item was not removed from list'); + expect(await dataTable.isItemPresent(file)).toBe(false, 'Item was not removed from list'); + expect(await dataTable.isItemPresent(folder)).toBe(false, 'Item was not removed from list'); await page.clickPersonalFilesAndWait(); - expect(await page.dataTable.getRowByName(file).isPresent()).toBe(true, 'Item not displayed in list'); - expect(await page.dataTable.getRowByName(folder).isPresent()).toBe(true, 'Item not displayed in list'); + expect(await page.dataTable.isItemPresent(file)).toBe(true, 'Item not displayed in list'); + expect(await page.dataTable.isItemPresent(folder)).toBe(true, 'Item not displayed in list'); await apis.user.nodes.deleteNodesById([fileId, folderId], false); }); it('View from notification - [C217181]', async () => { await dataTable.selectItem(file); - await toolbar.getButtonByTitleAttribute('Restore').click(); + await toolbar.clickRestore(); await page.clickSnackBarAction(); await page.dataTable.waitForHeader(); expect(await page.sidenav.isActive('Personal Files')).toBe(true, 'Personal Files sidebar link not active'); @@ -184,17 +182,15 @@ describe('Restore from Trash', () => { it('Restore a file when another file with same name exists on the restore location - [C217178]', async () => { await page.clickTrashAndWait(); await dataTable.selectItem(file1); - await toolbar.getButtonByTitleAttribute('Restore').click(); - const text = await page.getSnackBarMessage(); - expect(text).toEqual(`Can't restore, ${file1} already exists`); + await toolbar.clickRestore(); + expect(await page.getSnackBarMessage()).toEqual(`Can't restore, ${file1} already exists`); }); it('Restore a file when original location no longer exists - [C217179]', async () => { await page.clickTrashAndWait(); await dataTable.selectItem(file2); - await toolbar.getButtonByTitleAttribute('Restore').click(); - const text = await page.getSnackBarMessage(); - expect(text).toEqual(`Can't restore ${file2}, the original location no longer exists`); + await toolbar.clickRestore(); + expect(await page.getSnackBarMessage()).toEqual(`Can't restore ${file2}, the original location no longer exists`); }); }); @@ -254,16 +250,14 @@ describe('Restore from Trash', () => { it('one failure - [C217183]', async () => { await dataTable.selectMultipleItems([file1, file2]); - await toolbar.getButtonByTitleAttribute('Restore').click(); - const text = await page.getSnackBarMessage(); - expect(text).toEqual(`Can't restore ${file1}, the original location no longer exists`); + await toolbar.clickRestore(); + expect(await page.getSnackBarMessage()).toEqual(`Can't restore ${file1}, the original location no longer exists`); }); it('multiple failures - [C217184]', async () => { await dataTable.selectMultipleItems([file3, file4, file5]); - await toolbar.getButtonByTitleAttribute('Restore').click(); - const text = await page.getSnackBarMessage(); - expect(text).toEqual('2 items not restored because of issues with the restore location'); + await toolbar.clickRestore(); + expect(await page.getSnackBarMessage()).toEqual('2 items not restored because of issues with the restore location'); }); }); }); diff --git a/e2e/suites/actions/share-file.test.ts b/e2e/suites/actions/share-file.test.ts index 607ee4eec3..ddaafda7c2 100755 --- a/e2e/suites/actions/share-file.test.ts +++ b/e2e/suites/actions/share-file.test.ts @@ -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 @@ -120,7 +120,7 @@ describe('Share a file', () => { it('Share dialog default values - [C286327]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.getTitle()).toEqual(`Share ${file1}`); @@ -131,38 +131,38 @@ describe('Share a file', () => { expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); expect(await shareDialog.getLabels().get(1).getText()).toEqual('Expires on'); expect(await shareDialog.isExpireToggleEnabled()).toBe(false, 'Expire toggle is checked'); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); }); it('Close dialog - [C286328]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); await shareDialog.clickClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog is open'); }); it('Share a file - [C286329]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await Utils.pressEscape(); - const sharedId = await apis.user.nodes.getNodeProperty(file3Id, 'qshare:sharedId'); + const sharedId = await apis.user.nodes.getSharedId(file3Id); expect(await apis.user.nodes.isFileShared(file3Id)).toBe(true, `${file3} is not shared`); expect(url).toContain(sharedId); // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file3).isPresent()).toBe(true, `${file3} is not in the Shared files list`); + // expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} is not in the Shared files list`); }); it('Copy shared file URL - [C286330]', async () => { await dataTable.selectItem(file4); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); expect(url).toContain('/preview/s/'); @@ -179,7 +179,7 @@ describe('Share a file', () => { it('Share a file with expiration date - [C286332]', async () => { await dataTable.selectItem(file5); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); await shareDialog.clickExpirationToggle(); @@ -193,17 +193,17 @@ describe('Share a file', () => { expect(new Date(inputDate)).toEqual(new Date(setDate)); - const expireDateProperty = await apis.user.nodes.getNodeProperty(file5Id, 'qshare:expiryDate'); + const expireDateProperty = await apis.user.nodes.getSharedExpiryDate(file5Id); expect(Utils.formatDate(expireDateProperty)).toEqual(Utils.formatDate(inputDate)); }); it('Expire date is displayed correctly - [C286337]', async () => { await dataTable.selectItem(file6); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); - const expireProperty = await apis.user.nodes.getNodeProperty(file6Id, 'qshare:expiryDate'); + const expireProperty = await apis.user.nodes.getSharedExpiryDate(file6Id); expect(expireProperty).toEqual(expiryDate); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); expect(Utils.formatDate(await shareDialog.getExpireDate())).toEqual(Utils.formatDate(expiryDate)); @@ -211,7 +211,7 @@ describe('Share a file', () => { it('Disable the share link expiration - [C286333]', async () => { await dataTable.selectItem(file7); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); @@ -222,12 +222,12 @@ describe('Share a file', () => { expect(await shareDialog.getExpireDate()).toBe('', 'Expire date input is not empty'); await shareDialog.clickClose(); - expect(await apis.user.nodes.getNodeProperty(file7Id, 'qshare:expiryDate')).toBe(undefined, `${file7} link still has expiration`); + expect(await apis.user.nodes.getSharedExpiryDate(file7Id)).toBe(undefined, `${file7} link still has expiration`); }); it('Shared file URL is not changed when Share dialog is closed and opened again - [C286335]', async () => { await dataTable.selectItem(file8); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url1 = await shareDialog.getLinkUrl(); await shareDialog.clickClose(); @@ -235,7 +235,7 @@ describe('Share a file', () => { await page.dataTable.clearSelection(); await dataTable.selectItem(file8); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url2 = await shareDialog.getLinkUrl(); @@ -244,31 +244,31 @@ describe('Share a file', () => { it('Share a file from the context menu - [C286345]', async () => { await dataTable.rightClickOnItem(file9); - await contextMenu.clickShareAction(); + await contextMenu.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await Utils.pressEscape(); - const sharedId = await apis.user.nodes.getNodeProperty(file9Id, 'qshare:sharedId'); + const sharedId = await apis.user.nodes.getSharedId(file9Id); expect(await apis.user.nodes.isFileShared(file9Id)).toBe(true, `${file9} is not shared`); expect(url).toContain(sharedId); // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file9).isPresent()).toBe(true, `${file9} is not in the Shared files list`); + // expect(await dataTable.isItemPresent(file9)).toBe(true, `${file9} is not in the Shared files list`); }); }); describe('from File Libraries', () => { - const file1 = `file1-${Utils.random()}.txt`; let file1Id; - const file2 = `file2-${Utils.random()}.txt`; let file2Id; + const file1 = `file1-${Utils.random()}.txt`; + const file2 = `file2-${Utils.random()}.txt`; const file3 = `file3-${Utils.random()}.txt`; let file3Id; - const file4 = `file4-${Utils.random()}.txt`; let file4Id; + const file4 = `file4-${Utils.random()}.txt`; const file5 = `file5-${Utils.random()}.txt`; let file5Id; const file6 = `file6-${Utils.random()}.txt`; let file6Id; const file7 = `file7-${Utils.random()}.txt`; let file7Id; - const file8 = `file8-${Utils.random()}.txt`; let file8Id; + const file8 = `file8-${Utils.random()}.txt`; const file9 = `file9-${Utils.random()}.txt`; let file9Id; const siteName = `site-${Utils.random()}`; @@ -279,14 +279,14 @@ describe('Share a file', () => { const docLibId = await apis.user.sites.getDocLibId(siteName); parentInSiteId = (await apis.user.nodes.createFolder(parentInSite, docLibId)).entry.id; - file1Id = (await apis.user.nodes.createFile(file1, parentInSiteId)).entry.id; - file2Id = (await apis.user.nodes.createFile(file2, parentInSiteId)).entry.id; + await apis.user.nodes.createFile(file1, parentInSiteId); + await apis.user.nodes.createFile(file2, parentInSiteId); file3Id = (await apis.user.nodes.createFile(file3, parentInSiteId)).entry.id; - file4Id = (await apis.user.nodes.createFile(file4, parentInSiteId)).entry.id; + await apis.user.nodes.createFile(file4, parentInSiteId); file5Id = (await apis.user.nodes.createFile(file5, parentInSiteId)).entry.id; file6Id = (await apis.user.nodes.createFile(file6, parentInSiteId)).entry.id; file7Id = (await apis.user.nodes.createFile(file7, parentInSiteId)).entry.id; - file8Id = (await apis.user.nodes.createFile(file8, parentInSiteId)).entry.id; + await apis.user.nodes.createFile(file8, parentInSiteId); file9Id = (await apis.user.nodes.createFile(file9, parentInSiteId)).entry.id; await apis.user.shared.shareFileById(file6Id, expiryDate); await apis.user.shared.shareFileById(file7Id, expiryDate); @@ -295,7 +295,7 @@ describe('Share a file', () => { }); beforeEach(async (done) => { - await page.clickFileLibrariesAndWait(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); await dataTable.doubleClickOnRowByName(parentInSite); @@ -316,7 +316,7 @@ describe('Share a file', () => { it('Share dialog default values - [C286639]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.getTitle()).toEqual(`Share ${file1}`); @@ -327,38 +327,38 @@ describe('Share a file', () => { expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); expect(await shareDialog.getLabels().get(1).getText()).toEqual('Expires on'); expect(await shareDialog.isExpireToggleEnabled()).toBe(false, 'Expire toggle is checked'); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); }); it('Close dialog - [C286640]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); await shareDialog.clickClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog is open'); }); it('Share a file - [C286641]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await Utils.pressEscape(); - const sharedId = await apis.user.nodes.getNodeProperty(file3Id, 'qshare:sharedId'); + const sharedId = await apis.user.nodes.getSharedId(file3Id); expect(await apis.user.nodes.isFileShared(file3Id)).toBe(true, `${file3} is not shared`); expect(url).toContain(sharedId); // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file3).isPresent()).toBe(true, `${file3} is not in the Shared files list`); + // expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} is not in the Shared files list`); }); it('Copy shared file URL - [C286642]', async () => { await dataTable.selectItem(file4); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); expect(url).toContain('/preview/s/'); @@ -375,7 +375,7 @@ describe('Share a file', () => { it('Share a file with expiration date - [C286643]', async () => { await dataTable.selectItem(file5); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); await shareDialog.clickExpirationToggle(); @@ -389,17 +389,17 @@ describe('Share a file', () => { expect(new Date(inputDate)).toEqual(new Date(setDate)); - const expireDateProperty = await apis.user.nodes.getNodeProperty(file5Id, 'qshare:expiryDate'); + const expireDateProperty = await apis.user.nodes.getSharedExpiryDate(file5Id); expect(Utils.formatDate(expireDateProperty)).toEqual(Utils.formatDate(inputDate)); }); it('Expire date is displayed correctly - [C286644]', async () => { await dataTable.selectItem(file6); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); - const expireProperty = await apis.user.nodes.getNodeProperty(file6Id, 'qshare:expiryDate'); + const expireProperty = await apis.user.nodes.getSharedExpiryDate(file6Id); expect(expireProperty).toEqual(expiryDate); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); expect(Utils.formatDate(await shareDialog.getExpireDate())).toEqual(Utils.formatDate(expiryDate)); @@ -407,7 +407,7 @@ describe('Share a file', () => { it('Disable the share link expiration - [C286645]', async () => { await dataTable.selectItem(file7); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); @@ -418,12 +418,12 @@ describe('Share a file', () => { expect(await shareDialog.getExpireDate()).toBe('', 'Expire date input is not empty'); await shareDialog.clickClose(); - expect(await apis.user.nodes.getNodeProperty(file7Id, 'qshare:expiryDate')).toBe(undefined, `${file7} link still has expiration`); + expect(await apis.user.nodes.getSharedExpiryDate(file7Id)).toBe(undefined, `${file7} link still has expiration`); }); it('Shared file URL is not changed when Share dialog is closed and opened again - [C286646]', async () => { await dataTable.selectItem(file8); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url1 = await shareDialog.getLinkUrl(); await shareDialog.clickClose(); @@ -431,7 +431,7 @@ describe('Share a file', () => { await page.dataTable.clearSelection(); await dataTable.selectItem(file8); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url2 = await shareDialog.getLinkUrl(); @@ -440,18 +440,18 @@ describe('Share a file', () => { it('Share a file from the context menu - [C286647]', async () => { await dataTable.rightClickOnItem(file9); - await contextMenu.clickShareAction(); + await contextMenu.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await Utils.pressEscape(); - const sharedId = await apis.user.nodes.getNodeProperty(file9Id, 'qshare:sharedId'); + const sharedId = await apis.user.nodes.getSharedId(file9Id); expect(await apis.user.nodes.isFileShared(file9Id)).toBe(true, `${file9} is not shared`); expect(url).toContain(sharedId); // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file9).isPresent()).toBe(true, `${file9} is not in the Shared files list`); + // expect(await dataTable.isItemPresent(file9)).toBe(true, `${file9} is not in the Shared files list`); }); }); @@ -510,7 +510,7 @@ describe('Share a file', () => { it('Share dialog default values - [C286657]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.getTitle()).toEqual(`Share ${file1}`); @@ -521,38 +521,38 @@ describe('Share a file', () => { expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); expect(await shareDialog.getLabels().get(1).getText()).toEqual('Expires on'); expect(await shareDialog.isExpireToggleEnabled()).toBe(false, 'Expire toggle is checked'); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); }); it('Close dialog - [C286658]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); await shareDialog.clickClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog is open'); }); it('Share a file - [C286659]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await Utils.pressEscape(); - const sharedId = await apis.user.nodes.getNodeProperty(file3Id, 'qshare:sharedId'); + const sharedId = await apis.user.nodes.getSharedId(file3Id); expect(await apis.user.nodes.isFileShared(file3Id)).toBe(true, `${file3} is not shared`); expect(url).toContain(sharedId); // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file3).isPresent()).toBe(true, `${file3} is not in the Shared files list`); + // expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} is not in the Shared files list`); }); it('Copy shared file URL - [C286660]', async () => { await dataTable.selectItem(file4); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); expect(url).toContain('/preview/s/'); @@ -569,7 +569,7 @@ describe('Share a file', () => { it('Share a file with expiration date - [C286661]', async () => { await dataTable.selectItem(file5); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); await shareDialog.clickExpirationToggle(); @@ -583,17 +583,17 @@ describe('Share a file', () => { expect(new Date(inputDate)).toEqual(new Date(setDate)); - const expireDateProperty = await apis.user.nodes.getNodeProperty(file5Id, 'qshare:expiryDate'); + const expireDateProperty = await apis.user.nodes.getSharedExpiryDate(file5Id); expect(Utils.formatDate(expireDateProperty)).toEqual(Utils.formatDate(inputDate)); }); it('Expire date is displayed correctly - [C286662]', async () => { await dataTable.selectItem(file6); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); - const expireProperty = await apis.user.nodes.getNodeProperty(file6Id, 'qshare:expiryDate'); + const expireProperty = await apis.user.nodes.getSharedExpiryDate(file6Id); expect(expireProperty).toEqual(expiryDate); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); expect(Utils.formatDate(await shareDialog.getExpireDate())).toEqual(Utils.formatDate(expiryDate)); @@ -601,7 +601,7 @@ describe('Share a file', () => { it('Disable the share link expiration - [C286663]', async () => { await dataTable.selectItem(file7); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); @@ -612,12 +612,12 @@ describe('Share a file', () => { expect(await shareDialog.getExpireDate()).toBe('', 'Expire date input is not empty'); await shareDialog.clickClose(); - expect(await apis.user.nodes.getNodeProperty(file7Id, 'qshare:expiryDate')).toBe(undefined, `${file7} link still has expiration`); + expect(await apis.user.nodes.getSharedExpiryDate(file7Id)).toBe(undefined, `${file7} link still has expiration`); }); it('Shared file URL is not changed when Share dialog is closed and opened again - [C286664]', async () => { await dataTable.selectItem(file8); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url1 = await shareDialog.getLinkUrl(); await shareDialog.clickClose(); @@ -625,7 +625,7 @@ describe('Share a file', () => { await page.dataTable.clearSelection(); await dataTable.selectItem(file8); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url2 = await shareDialog.getLinkUrl(); @@ -634,18 +634,18 @@ describe('Share a file', () => { it('Share a file from the context menu - [C286665]', async () => { await dataTable.rightClickOnItem(file9); - await contextMenu.clickShareAction(); + await contextMenu.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await Utils.pressEscape(); - const sharedId = await apis.user.nodes.getNodeProperty(file9Id, 'qshare:sharedId'); + const sharedId = await apis.user.nodes.getSharedId(file9Id); expect(await apis.user.nodes.isFileShared(file9Id)).toBe(true, `${file9} is not shared`); expect(url).toContain(sharedId); // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file9).isPresent()).toBe(true, `${file9} is not in the Shared files list`); + // expect(await dataTable.isItemPresent(file9)).toBe(true, `${file9} is not in the Shared files list`); }); }); @@ -704,7 +704,7 @@ describe('Share a file', () => { it('Share dialog default values - [C286648]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.getTitle()).toEqual(`Share ${file1}`); @@ -715,22 +715,22 @@ describe('Share a file', () => { expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); expect(await shareDialog.getLabels().get(1).getText()).toEqual('Expires on'); expect(await shareDialog.isExpireToggleEnabled()).toBe(false, 'Expire toggle is checked'); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); }); it('Close dialog - [C286649]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); await shareDialog.clickClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog is open'); }); it('Copy shared file URL - [C286651]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); expect(url).toContain('/preview/s/'); @@ -747,10 +747,10 @@ describe('Share a file', () => { it('Expire date is displayed correctly - [C286653]', async () => { await dataTable.selectItem(file4); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); - const expireProperty = await apis.user.nodes.getNodeProperty(file4Id, 'qshare:expiryDate'); + const expireProperty = await apis.user.nodes.getSharedExpiryDate(file4Id); expect(expireProperty).toEqual(expiryDate); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); expect(Utils.formatDate(await shareDialog.getExpireDate())).toEqual(Utils.formatDate(expiryDate)); @@ -758,7 +758,7 @@ describe('Share a file', () => { it('Disable the share link expiration - [C286654]', async () => { await dataTable.selectItem(file5); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); @@ -769,12 +769,12 @@ describe('Share a file', () => { expect(await shareDialog.getExpireDate()).toBe('', 'Expire date input is not empty'); await shareDialog.clickClose(); - expect(await apis.user.nodes.getNodeProperty(file5Id, 'qshare:expiryDate')).toBe(undefined, `${file5} link still has expiration`); + expect(await apis.user.nodes.getSharedExpiryDate(file5Id)).toBe(undefined, `${file5} link still has expiration`); }); it('Shared file URL is not changed when Share dialog is closed and opened again - [C286655]', async () => { await dataTable.selectItem(file6); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url1 = await shareDialog.getLinkUrl(); await shareDialog.clickClose(); @@ -782,7 +782,7 @@ describe('Share a file', () => { await page.dataTable.clearSelection(); await dataTable.selectItem(file6); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url2 = await shareDialog.getLinkUrl(); @@ -791,7 +791,7 @@ describe('Share a file', () => { it('Open Share dialog from context menu - [C286656]', async () => { await dataTable.rightClickOnItem(file7); - await contextMenu.clickShareEditAction(); + await contextMenu.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.getTitle()).toEqual(`Share ${file7}`); @@ -802,11 +802,10 @@ describe('Share a file', () => { expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); expect(await shareDialog.getLabels().get(1).getText()).toEqual('Expires on'); expect(await shareDialog.isExpireToggleEnabled()).toBe(false, 'Expire toggle is checked'); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); }); }); - // TODO: enable when ACA-1886 is done describe('from Favorites', () => { const file1 = `file1-${Utils.random()}.txt`; let file1Id; @@ -873,7 +872,7 @@ describe('Share a file', () => { it('Share dialog default values - [C286666]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.getTitle()).toEqual(`Share ${file1}`); @@ -884,38 +883,38 @@ describe('Share a file', () => { expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); expect(await shareDialog.getLabels().get(1).getText()).toEqual('Expires on'); expect(await shareDialog.isExpireToggleEnabled()).toBe(false, 'Expire toggle is checked'); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); }); it('Close dialog - [C286667]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); - expect(await shareDialog.closeButton.isEnabled()).toBe(true, 'Close button is not enabled'); + expect(await shareDialog.isCloseEnabled()).toBe(true, 'Close button is not enabled'); await shareDialog.clickClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog is open'); }); it('Share a file - [C286668]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await Utils.pressEscape(); - const sharedId = await apis.user.nodes.getNodeProperty(file3Id, 'qshare:sharedId'); + const sharedId = await apis.user.nodes.getSharedId(file3Id); expect(await apis.user.nodes.isFileShared(file3Id)).toBe(true, `${file3} is not shared`); expect(url).toContain(sharedId); // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file3).isPresent()).toBe(true, `${file3} is not in the Shared files list`); + // expect(await dataTable.isItemPresent(file3)).toBe(true, `${file3} is not in the Shared files list`); }); it('Copy shared file URL - [C286669]', async () => { await dataTable.selectItem(file4); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); expect(url).toContain('/preview/s/'); @@ -932,7 +931,7 @@ describe('Share a file', () => { it('Share a file with expiration date - [C286670]', async () => { await dataTable.selectItem(file5); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); await shareDialog.clickExpirationToggle(); @@ -946,17 +945,17 @@ describe('Share a file', () => { expect(new Date(inputDate)).toEqual(new Date(setDate)); - const expireDateProperty = await apis.user.nodes.getNodeProperty(file5Id, 'qshare:expiryDate'); + const expireDateProperty = await apis.user.nodes.getSharedExpiryDate(file5Id); expect(Utils.formatDate(expireDateProperty)).toEqual(Utils.formatDate(inputDate)); }); it('Expire date is displayed correctly - [C286671]', async () => { await dataTable.selectItem(file6); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); - const expireProperty = await apis.user.nodes.getNodeProperty(file6Id, 'qshare:expiryDate'); + const expireProperty = await apis.user.nodes.getSharedExpiryDate(file6Id); expect(expireProperty).toEqual(expiryDate); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); expect(Utils.formatDate(await shareDialog.getExpireDate())).toEqual(Utils.formatDate(expiryDate)); @@ -964,7 +963,7 @@ describe('Share a file', () => { it('Disable the share link expiration - [C286672]', async () => { await dataTable.selectItem(file7); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isExpireToggleEnabled()).toBe(true, 'Expiration is not checked'); @@ -975,12 +974,12 @@ describe('Share a file', () => { expect(await shareDialog.getExpireDate()).toBe('', 'Expire date input is not empty'); await shareDialog.clickClose(); - expect(await apis.user.nodes.getNodeProperty(file7Id, 'qshare:expiryDate')).toBe(undefined, `${file7} link still has expiration`); + expect(await apis.user.nodes.getSharedExpiryDate(file7Id)).toBe(undefined, `${file7} link still has expiration`); }); it('Shared file URL is not changed when Share dialog is closed and opened again - [C286673]', async () => { await dataTable.selectItem(file8); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url1 = await shareDialog.getLinkUrl(); await shareDialog.clickClose(); @@ -988,7 +987,7 @@ describe('Share a file', () => { await page.dataTable.clearSelection(); await dataTable.selectItem(file8); - await toolbar.clickShareButton(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url2 = await shareDialog.getLinkUrl(); @@ -997,21 +996,19 @@ describe('Share a file', () => { it('Share a file from the context menu - [C286674]', async () => { await dataTable.rightClickOnItem(file9); - await contextMenu.clickMenuItem('Share'); + await contextMenu.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await Utils.pressEscape(); - const sharedId = await apis.user.nodes.getNodeProperty(file9Id, 'qshare:sharedId'); + const sharedId = await apis.user.nodes.getSharedId(file9Id); expect(await apis.user.nodes.isFileShared(file9Id)).toBe(true, `${file9} is not shared`); expect(url).toContain(sharedId); // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file9).isPresent()).toBe(true, `${file9} is not in the Shared files list`); + // expect(await dataTable.isItemPresent(file9)).toBe(true, `${file9} is not in the Shared files list`); }); }); - xit(''); - }); diff --git a/e2e/suites/actions/single-click.test.ts b/e2e/suites/actions/single-click.test.ts index 6e53f78f23..870e7b1c44 100755 --- a/e2e/suites/actions/single-click.test.ts +++ b/e2e/suites/actions/single-click.test.ts @@ -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 @@ -129,7 +129,7 @@ describe('Single click on item name', () => { await dataTable.clickNameLink(siteName); expect(await breadcrumb.getCurrentItemName()).toBe(siteName); - expect(await dataTable.getRowByName(fileSite).isPresent()).toBe(true, `${fileSite} not displayed`); + expect(await dataTable.isItemPresent(fileSite)).toBe(true, `${fileSite} not displayed`); }); }); diff --git a/e2e/suites/actions/special-permissions-available-actions.test.ts b/e2e/suites/actions/special-permissions-available-actions.test.ts index 72816829b4..06a76ed684 100755 --- a/e2e/suites/actions/special-permissions-available-actions.test.ts +++ b/e2e/suites/actions/special-permissions-available-actions.test.ts @@ -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,27 +23,31 @@ * along with Alfresco. If not, see . */ -import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { LoginPage, BrowsingPage, SearchResultsPage } from '../../pages/pages'; import { SITE_VISIBILITY, SITE_ROLES, FILES } from '../../configs'; import { RepoClient } from '../../utilities/repo-client/repo-client'; import { Utils } from '../../utilities/utils'; import { Viewer } from '../../components/viewer/viewer'; -describe('Granular permissions available actions : ', () => { +describe('Special permissions available actions : ', () => { const userConsumer = `consumer-${Utils.random()}`; const userManager = `manager-${Utils.random()}`; + const userCollaborator = `collaborator-${Utils.random()}`; + const userDemoted = `demoted-${Utils.random()}`; const siteName = `site-private-${Utils.random()}`; - const file1 = `file1-${Utils.random()}.txt`; + const file1 = `my-file1-${Utils.random()}.txt`; let file1Id; - const file2 = `file2-${Utils.random()}.txt`; + const file2 = `my-file2-${Utils.random()}.txt`; let file2Id; - const file3 = `file3-${Utils.random()}.txt`; + const file3 = `my-file3-${Utils.random()}.txt`; let file3Id; + const fileLocked = `my-file-locked-${Utils.random()}.txt`; + let fileLockedId; - const folder1 = `folder1-${Utils.random()}`; + const folder1 = `my-folder1-${Utils.random()}`; let folder1Id; - const folder2 = `folder2-${Utils.random()}`; + const folder2 = `my-folder2-${Utils.random()}`; let folder2Id; const docxFile = FILES.docxFile; @@ -52,7 +56,8 @@ describe('Granular permissions available actions : ', () => { const apis = { admin: new RepoClient(), userConsumer: new RepoClient(userConsumer, userConsumer), - userManager: new RepoClient(userManager, userManager) + userCollaborator: new RepoClient(userCollaborator, userCollaborator), + userDemoted: new RepoClient(userDemoted, userDemoted) }; const loginPage = new LoginPage(); @@ -61,10 +66,14 @@ describe('Granular permissions available actions : ', () => { const contextMenu = dataTable.menu; const viewer = new Viewer(); const viewerToolbar = viewer.toolbar; + const searchResultsPage = new SearchResultsPage(); + const { searchInput } = searchResultsPage.header; - beforeAll(async done => { + beforeAll(async (done) => { await apis.admin.people.createUser({ username: userConsumer }); await apis.admin.people.createUser({ username: userManager }); + await apis.admin.people.createUser({ username: userCollaborator }); + await apis.admin.people.createUser({ username: userDemoted }); await apis.admin.sites.createSite(siteName, SITE_VISIBILITY.PRIVATE); const docLibId = await apis.admin.sites.getDocLibId(siteName); @@ -79,6 +88,14 @@ describe('Granular permissions available actions : ', () => { await apis.admin.sites.addSiteMember(siteName, userManager, SITE_ROLES.SITE_MANAGER.ROLE); await apis.admin.sites.addSiteMember(siteName, userConsumer, SITE_ROLES.SITE_CONSUMER.ROLE); + await apis.admin.sites.addSiteMember(siteName, userCollaborator, SITE_ROLES.SITE_COLLABORATOR.ROLE); + await apis.admin.sites.addSiteMember(siteName, userDemoted, SITE_ROLES.SITE_MANAGER.ROLE); + + fileLockedId = (await apis.admin.nodes.createFile(fileLocked, docLibId)).entry.id; + await apis.userDemoted.nodes.lockFile(fileLockedId); + await apis.userDemoted.favorites.addFavoriteById('file', fileLockedId); + await apis.userDemoted.shared.shareFileById(fileLockedId); + await apis.admin.sites.updateSiteMember(siteName, userDemoted, SITE_ROLES.SITE_CONSUMER.ROLE); await apis.admin.nodes.setGranularPermission(file3Id, false, userConsumer, SITE_ROLES.SITE_MANAGER.ROLE); @@ -86,605 +103,1786 @@ describe('Granular permissions available actions : ', () => { await apis.userConsumer.shared.shareFileById(file2Id); await apis.userConsumer.shared.shareFileById(docxFileId); await apis.userConsumer.shared.shareFileById(file3Id); - await apis.userConsumer.shared.waitForApi({ expect: 4 }); + await apis.userConsumer.shared.waitForApi({ expect: 5 }); await apis.userConsumer.favorites.addFavoritesByIds('file', [file1Id, file2Id, file3Id, docxFileId]); await apis.userConsumer.favorites.addFavoritesByIds('folder', [folder1Id, folder2Id]); await apis.userConsumer.favorites.waitForApi({ expect: 6 }); - await loginPage.loginWith(userConsumer); + await apis.userCollaborator.favorites.addFavoritesByIds('file', [file1Id, docxFileId]); + await apis.userCollaborator.favorites.waitForApi({ expect: 2 }); + + await apis.admin.favorites.addFavoriteById('file', fileLockedId); + done(); }); - afterAll(async done => { + afterAll(async (done) => { await apis.admin.sites.deleteSite(siteName); done(); }); - xit(''); - - describe('toolbar displays correct actions when selecting multiple files with different granular permissions', () => { - beforeEach(async done => { - await Utils.pressEscape(); + describe('Consumer', () => { + beforeAll(async (done) => { + await loginPage.loginWith(userConsumer); done(); }); - it('on File Libraries - [C280476]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for selected files`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for selected files`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for selected files`); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); - await toolbar.closeMoreMenu(); + describe('toolbar displays correct actions when selecting multiple files with different granular permissions', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280476]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectMultipleItems([file1, file2]); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for selected files`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for selected files`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for selected files`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for selected files`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for selected files`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for selected files`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for selected files`); + + await toolbar.closeMoreMenu(); + }); + + it('on Shared Files - [C280477]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.selectMultipleItems([file1, file2]); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for selected files`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for selected files`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for selected files`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for selected files`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for selected files`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for selected files`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for selected files`); + + await toolbar.closeMoreMenu(); + }); + + it('on Favorites - [C280478]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectMultipleItems([file1, file2]); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for selected files`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for selected files`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for selected files`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for selected files`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is displayed for selected files`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for selected files`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for selected files`); + + await toolbar.closeMoreMenu(); + }); + + it('on Search Results - [C291823]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions('my-file'); + await dataTable.selectMultipleItems([file1, file2]); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for selected files`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for selected files`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for selected files`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for selected files`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for selected files`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for selected files`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for selected files`); + + await toolbar.closeMoreMenu(); + }); }); - it('on Shared Files - [C280477]', async () => { - await page.clickSharedFilesAndWait(); - await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for selected files`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for selected files`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for selected files`); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); - await toolbar.closeMoreMenu(); + describe('toolbar actions appear correctly for a file', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280455]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectItem(file1); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${file1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${file1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${file1}`); + + await toolbar.closeMoreMenu(); + }); + + it('on Shared Files - [C280456]', async () => { + await page.clickSharedFilesAndWait(); + await page.dataTable.selectItem(file1); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${file1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${file1}`); + // TODO: change expect to false when ACA-2173 is done + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is displayed for ${file1}`); + + await toolbar.closeMoreMenu(); + }); + + it('on Favorites - [C213121]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectItem(file1); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${file1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + // TODO: replace with isSharedLinkSettingsPresent when ACA-2175 is done + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for ${file1}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is displayed for ${file1}`); + + await toolbar.closeMoreMenu(); + }); + + it('on Search Results - [C291818]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions(file1); + await dataTable.selectItem(file1); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${file1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${file1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${file1}`); + + await toolbar.closeMoreMenu(); + }); }); - it('on Favorites - [C280478]', async () => { - await page.clickFavoritesAndWait(); - await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for selected files`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for selected files`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for selected files`); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - // TODO: enable when ACA-1737 is done - // expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for selected files`); - // expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); - await toolbar.closeMoreMenu(); + describe('toolbar actions appear correctly for a folder', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280444]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectItem(folder1); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for ${folder1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${folder1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${folder1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${folder1}`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folder1}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${folder1}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${folder1}`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folder1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folder1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); + + await toolbar.closeMoreMenu(); + }); + + it('on Favorites - [C286266]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectItem(folder1); + + expect(await toolbar.isViewPresent()).toBe(false, `View is not displayed for ${folder1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${folder1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${folder1}`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isEditFolderPresent()).toBe(true, `Edit folder is displayed for ${folder1}`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folder1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is displayed for ${folder1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for ${folder1}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folder1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folder1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); + + await toolbar.closeMoreMenu(); + }); + + it('on Search Results - [C291819]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFolders(); + await searchInput.searchForTextAndCloseSearchOptions(folder1); + await dataTable.selectItem(folder1); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for ${folder1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${folder1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${folder1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${folder1}`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folder1}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${folder1}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${folder1}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folder1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folder1}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); + + await toolbar.closeMoreMenu(); + }); + }); + + describe('toolbar actions appear correctly for multiple selection of files', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280464]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectMultipleItems([file1, file2]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('on Shared Files - [C286284]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.selectMultipleItems([file1, file2]); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for selected files`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for selected files`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for selected files`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('on Favorites - [C286285]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectMultipleItems([file1, file2]); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for selected files`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for selected files`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for selected files`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is displayed for selected files`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('on Search Results - [C291824]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions('my-file'); + await dataTable.selectMultipleItems([file1, file2]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + }); + + describe('toolbar actions appear correctly for multiple selection of folders', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280465]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectMultipleItems([folder1, folder2]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('on Favorites - [C286286]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectMultipleItems([folder1, folder2]); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is displayed`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('on Search Results - [C291825]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFolders(); + await searchInput.searchForTextAndCloseSearchOptions('my-folder'); + await dataTable.selectMultipleItems([folder1, folder2]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + }); + + describe('toolbar actions appear correctly for when both files and folders are selected', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280466]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectMultipleItems([file1, folder1]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('on Favorites - [C286287]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectMultipleItems([file1, folder1]); + + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed`); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is displayed`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('on Search Results - [C291826]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkFilesAndFolders(); + await searchInput.searchForTextAndCloseSearchOptions('my-f'); + await dataTable.selectMultipleItems([file1, folder1]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + expect(await toolbar.isSharePresent()).toBe(false, `Share is displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + }); + + describe('context menu actions are correct for a file', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280599]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.rightClickOnItem(file1); + + expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${file1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${file1}`); + expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${file1}`); + expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + }); + + it('on Shared Files - [C286264]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.rightClickOnItem(file1); + + expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed for ${file1}`); + expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${file1}`); + // TODO: change expect to false when ACA-2173 is done + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is displayed for ${file1}`); + expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${file1}`); + }); + + it('on Favorites - [C286262]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.rightClickOnItem(file1); + + expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isMovePresent()).toBe(true, `Move is displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is displayed for ${file1}`); + // TODO: replace with isSharedLinkSettingsPresent when ACA-2175 is done + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isUploadNewVersionPresent()).toBe(true, `Upload new version is displayed for ${file1}`); + expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${file1}`); + }); + + it('on Search Results - [C291829]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions(file1); + await dataTable.rightClickOnItem(file1); + + expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await contextMenu.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await contextMenu.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + expect(await contextMenu.isManageVersionsPresent()).toBe(true, `Manage Versions is not displayed for ${file1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${file1}`); + expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await contextMenu.isViewDetailsPresent()).toBe(false, `View details is displayed for ${file1}`); + }); + }); + + describe('context menu actions are correct for a folder', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280600]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.rightClickOnItem(folder1); + + expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${folder1}`); + expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${folder1}`); + expect(await contextMenu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folder1}`); + expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folder1}`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${folder1}`); + expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${folder1}`); + expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folder1}`); + expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folder1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folder1}`); + expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); + expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); + }); + + it('on Favorites - [C286263]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.rightClickOnItem(folder1); + + expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${folder1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isEditFolderPresent()).toBe(true, `Edit folder is displayed for ${folder1}`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folder1}`); + expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folder1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isMovePresent()).toBe(true, `Move is displayed for ${folder1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is displayed for ${folder1}`); + expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folder1}`); + expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folder1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folder1}`); + expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); + expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); + }); + + it('on Search Results - [C291830]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFolders(); + await searchInput.searchForTextAndCloseSearchOptions(folder1); + await dataTable.rightClickOnItem(folder1); + + expect(await contextMenu.isDownloadPresent()).toBe(true, `Download is not displayed for ${folder1}`); + expect(await contextMenu.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${folder1}`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folder1}`); + expect(await contextMenu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folder1}`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed for ${folder1}`); + expect(await contextMenu.isDeletePresent()).toBe(false, `Delete is displayed for ${folder1}`); + expect(await contextMenu.isViewPresent()).toBe(false, `View is displayed for ${folder1}`); + expect(await contextMenu.isManageVersionsPresent()).toBe(false, `Manage Versions is displayed for ${folder1}`); + expect(await contextMenu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folder1}`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed for ${folder1}`); + expect(await contextMenu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folder1}`); + expect(await contextMenu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folder1}`); + }); + }); + + describe('context menu actions are correct for multiple selection of files', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280647]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectMultipleItems([file1, file2]); + 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(false, `Delete is displayed`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is 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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + + it('on Shared Files - [C286283]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.selectMultipleItems([file1, file2]); + 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(false, `Delete is displayed`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + + it('on Favorites - [C286280]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectMultipleItems([file1, file2]); + 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`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is displayed`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isMovePresent()).toBe(true, `Move is displayed`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + + it('on Search Results - [C291834]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions('my-file'); + await dataTable.selectMultipleItems([file1, file2]); + 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(false, `Delete is displayed`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + }); + + describe('context menu actions are correct for multiple selection of folders', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280666]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectMultipleItems([folder1, folder2]); + 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.isEditFolderPresent()).toBe(false, `Edit folder 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(false, `Delete is displayed`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is 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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + + it('on Favorites - [C286281]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectMultipleItems([folder1, folder2]); + 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.isEditFolderPresent()).toBe(false, `Edit folder 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`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is displayed`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isMovePresent()).toBe(true, `Move is displayed`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + + it('on Search Results - [C291835]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFolders(); + await searchInput.searchForTextAndCloseSearchOptions('my-folder'); + await dataTable.selectMultipleItems([folder1, folder2]); + 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.isEditFolderPresent()).toBe(false, `Edit folder 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(false, `Delete is displayed`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + }); + + describe('context menu actions are correct when both files and folders are selected', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('on File Libraries - [C280669]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.selectMultipleItems([file1, folder1]); + 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(false, `Delete is displayed`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is 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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + + it('on Favorites - [C286282]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.selectMultipleItems([file1, folder1]); + 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`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isDeletePresent()).toBe(true, `Delete is displayed`); + // TODO: change expect to false when ACA-1737 is done + expect(await contextMenu.isMovePresent()).toBe(true, `Move is displayed`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + + it('on Search Results - [C291836]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkFilesAndFolders(); + await searchInput.searchForTextAndCloseSearchOptions('my-f'); + await dataTable.selectMultipleItems([file1, folder1]); + 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(false, `Delete is displayed`); + expect(await contextMenu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await contextMenu.isToggleRemoveFavoritePresent()).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`); + expect(await contextMenu.isSharePresent()).toBe(false, `Share is displayed`); + }); + }); + + describe('toolbar actions appear correctly in the viewer', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('file from File Libraries - [C268128]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.doubleClickOnRowByName(docxFile); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await viewerToolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('file from Shared Files - [C286310]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.doubleClickOnRowByName(docxFile); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('file from Favorites - [C286311]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.doubleClickOnRowByName(docxFile); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); }); }); - describe('toolbar actions appear correctly for a file - consumer', () => { - beforeEach(async done => { - await Utils.pressEscape(); + describe('Collaborator', () => { + beforeAll(async (done) => { + await loginPage.loginWith(userCollaborator); done(); }); - it('on File Libraries - [C280455]', async () => { + it('on File Libraries - [C297647]', async () => { await page.clickFileLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); await dataTable.selectItem(file1); - expect(await toolbar.isButtonPresent('View')).toBe(true, `View is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${file1}`); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${file1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${file1}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${file1}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${file1}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${file1}`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${file1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + await toolbar.closeMoreMenu(); }); - it('on Shared Files - [C280456]', async () => { + it('on Shared Files - [C297651]', async () => { await page.clickSharedFilesAndWait(); await page.dataTable.selectItem(file1); - expect(await toolbar.isButtonPresent('View')).toBe(true, `View is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${file1}`); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${file1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${file1}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${file1}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${file1}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${file1}`); + // TODO: change expect to true when ACA-2173 is done + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${file1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + await toolbar.closeMoreMenu(); }); - it('on Favorites - [C213121]', async () => { + it('on Favorites - [C297652]', async () => { await page.clickFavoritesAndWait(); await dataTable.selectItem(file1); - expect(await toolbar.isButtonPresent('View')).toBe(true, `View is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${file1}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${file1}`); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${file1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + // TODO: replace with isSharedLinkSettingsPresent when ACA-2175 is done + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${file1}`); - // TODO: enable when ACA-1737 is done - // expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${file1}`); - // expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${file1}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${file1}`); + + // TODO: change expect to true when ACA-2174 is done + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is not displayed for ${file1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is displayed for ${file1}`); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for ${file1}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + await toolbar.closeMoreMenu(); }); - }); - describe('toolbar actions appear correctly for a folder - consumer', () => { - beforeEach(async done => { - await Utils.pressEscape(); - done(); - }); + it('on Search Results - [C297653]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions(file1); + await dataTable.selectItem(file1); - it('on File Libraries - [C280444]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - await dataTable.selectItem(folder1); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for ${folder1}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${folder1}`); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${folder1}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${folder1}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${file1}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${file1}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${file1}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${file1}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folder1}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${folder1}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${folder1}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folder1}`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${file1}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${file1}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${file1}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${file1}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${file1}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${file1}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + await toolbar.closeMoreMenu(); }); - it('on Favorites - [C286266]', async () => { - await page.clickFavoritesAndWait(); - await dataTable.selectItem(folder1); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is not displayed for ${folder1}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${folder1}`); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${folder1}`); - // TODO: enable when ACA-1737 is done - // expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${folder1}`); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folder1}`); - // TODO: enable when ACA-1737 is done - // expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${folder1}`); - // expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${folder1}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folder1}`); - await toolbar.closeMoreMenu(); + describe('in the viewer', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('file opened from File Libraries - [C297654]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.doubleClickOnRowByName(docxFile); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + + it('file opened from Shared Files - [C297655]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.doubleClickOnRowByName(docxFile); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + + it('file opened from Favorites - [C297656]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.doubleClickOnRowByName(docxFile); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove Favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await viewerToolbar.closeMoreMenu(); + }); }); }); - describe('toolbar actions appear correctly for multiple selection of files - consumer', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await dataTable.clearSelection(); + describe('File locked - lock owner : ', () => { + beforeAll(async (done) => { + await loginPage.loginWith(userDemoted); done(); }); - it('on File Libraries - [C280464]', async () => { + it('on File Libraries - [C297657]', async () => { await page.clickFileLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); - await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is not displayed'); + await toolbar.closeMoreMenu(); }); - it('on Shared Files - [C286284]', async () => { + it('on Shared Files - [C297658]', async () => { await page.clickSharedFilesAndWait(); - await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for selected files`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for selected files`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for selected files`); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); - await toolbar.closeMoreMenu(); - }); + await page.dataTable.selectItem(fileLocked); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); - it('on Favorites - [C286285]', async () => { - await page.clickFavoritesAndWait(); - await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for selected files`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for selected files`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for selected files`); await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - // TODO: enable when ACA-1737 is done - // expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for selected files`); - // expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); - await toolbar.closeMoreMenu(); - }); - }); - describe('toolbar actions appear correctly for multiple selection of folders - consumer', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await dataTable.clearSelection(); - done(); - }); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + // TODO: change expect to true when ACA-2173 is done + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is not displayed'); - it('on File Libraries - [C280465]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - await dataTable.selectMultipleItems([folder1, folder2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); await toolbar.closeMoreMenu(); }); - it('on Favorites - [C286286]', async () => { + it('on Favorites - [C297659]', async () => { await page.clickFavoritesAndWait(); - await dataTable.selectMultipleItems([folder1, folder2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for selected files`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for selected files`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for selected files`); + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + // TODO: replace with isSharedLinkSettingsPresent when ACA-2175 is done + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - // TODO: enable when ACA-1737 is done - // expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for selected files`); - // expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + // TODO: change expect to true when ACA-2174 is fixed + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + // TODO: change expect to false when ACA-1737 is fixed + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is displayed for ${fileLocked}`); + // TODO: change expect to false when ACA-1737 is fixed + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is not displayed'); + await toolbar.closeMoreMenu(); }); - }); - describe('toolbar actions appear correctly for when both files and folders are selected - consumer', () => { - beforeEach(async done => { - await Utils.pressEscape(); - await dataTable.clearSelection(); - done(); - }); + it('on Search Results - [C297660]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions(fileLocked); + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); - it('on File Libraries - [C280466]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - await dataTable.selectMultipleItems([file1, folder1]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is not displayed'); + await toolbar.closeMoreMenu(); }); - it('on Favorites - [C286287]', async () => { - await page.clickFavoritesAndWait(); - await dataTable.selectMultipleItems([file1, folder1]); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for selected files`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for selected files`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for selected files`); - await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - // TODO: enable when ACA-1737 is done - // expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for selected files`); - // expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); - await toolbar.closeMoreMenu(); + describe('in the viewer', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('file opened from File Libraries - [C297661]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + + it('file opened from Shared Files - [C297662]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + + it('file opened from Favorites - [C297663]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(false, `Move is displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await viewerToolbar.closeMoreMenu(); + }); }); }); - describe('context menu actions are correct for a file - consumer', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); + describe('File locked - manager : ', () => { + beforeAll(async (done) => { + await loginPage.loginWithAdmin(); done(); }); - it('on File Libraries - [C280599]', async () => { + it('on File Libraries - [C297664]', async () => { await page.clickFileLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); - await dataTable.rightClickOnItem(file1); - expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('View')).toBe(true, `View is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${file1}`); - }); + await dataTable.selectItem(fileLocked); - it('on Shared Files - [C286264]', async () => { - await page.clickSharedFilesAndWait(); - await dataTable.rightClickOnItem(file1); - expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('View')).toBe(true, `View is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${file1}`); - // TODO: enable this when the action is properly implemented: ACA-92 - // expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${file1}`); - }); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); - it('on Favorites - [C286262]', async () => { - await page.clickFavoritesAndWait(); - await dataTable.rightClickOnItem(file1); - expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('View')).toBe(true, `View is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${file1}`); - // TODO: enable when ACA-1737 is done - // expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${file1}`); - // expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Share')).toBe(true, `Share is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage Versions is not displayed for ${file1}`); - // TODO: enable when ACA-1794 is fixed - // expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${file1}`); - expect(await contextMenu.isMenuItemPresent('View details')).toBe(false, `View details is displayed for ${file1}`); - }); - }); + await toolbar.openMoreMenu(); - describe('context menu actions are correct for a folder - consumer', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - done(); - }); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, 'Upload new version is displayed'); - it('on File Libraries - [C280600]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - await dataTable.rightClickOnItem(folder1); - expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not enabled for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('View')).toBe(false, `View is displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(false, `Manage Versions displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Share')).toBe(false, `Share is displayed for ${folder1}`); + await toolbar.closeMoreMenu(); }); - it('on Favorites - [C286263]', async () => { - await page.clickFavoritesAndWait(); - await dataTable.rightClickOnItem(folder1); - expect(await contextMenu.isMenuItemPresent('Download')).toBe(true, `Download is not enabled for ${folder1}`); - // enable when ACA-1737 is done - // expect(await contextMenu.isMenuItemPresent('Edit')).toBe(false, `Edit is displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folder1}`); - // TODO: enable when ACA-1737 is done - // expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed for ${folder1}`); - // expect(await contextMenu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed for ${folder1}`); - // TODO: enable when ACA-1794 is fixed - // expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('View')).toBe(false, `View is displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Manage Versions')).toBe(false, `Manage Versions is displayed for ${folder1}`); - expect(await contextMenu.isMenuItemPresent('Share')).toBe(false, `Share is displayed for ${folder1}`); - }); - }); + it('on Shared Files - [C297665]', async () => { + await page.clickSharedFilesAndWait(); + await page.dataTable.selectItem(fileLocked); - describe('context menu actions are correct for multiple selection of files - consumer', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await dataTable.clearSelection(); - done(); - }); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); - it('on File Libraries - [C280647]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - 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(false, `Delete is displayed`); - expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); - }); + await toolbar.openMoreMenu(); - it('on Shared Files - [C286283]', async () => { - await page.clickSharedFilesAndWait(); - 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(false, `Delete is displayed`); - expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + // TODO: change expect to true when ACA-2173 is done + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + // TODO: change expect to false when ACA-2173 is done + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is displayed'); + + await toolbar.closeMoreMenu(); }); - it('on Favorites - [C286280]', async () => { + it('on Favorites - [C297666]', async () => { await page.clickFavoritesAndWait(); - 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`); - // TODO: enable when ACA-1737 is done - // 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(true, `Favorite is not displayed`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); - }); - }); + await dataTable.selectItem(fileLocked); - describe('context menu actions are correct for multiple selection of folders - consumer', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await dataTable.clearSelection(); - done(); - }); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + // TODO: replace with isSharedLinkSettingsPresent when ACA-2175 is done + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); - it('on File Libraries - [C280666]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - 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('Copy')).toBe(true, `Copy is not 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(true, `Favorite is not displayed`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); - }); + await toolbar.openMoreMenu(); - it('on Favorites - [C286281]', async () => { - await page.clickFavoritesAndWait(); - 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('Copy')).toBe(true, `Copy is not displayed`); - // TODO: enable when ACA-1737 is done - // 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(true, `Favorite is not displayed`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); - }); - }); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + // TODO: change expect to true when ACA-2174 is fixed + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + // TODO: change expect to false when ACA-1737 is done + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, 'Upload new version is displayed'); - describe('context menu actions are correct when both files and folders are selected - consumer', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await dataTable.clearSelection(); - done(); + await toolbar.closeMoreMenu(); }); - it('on File Libraries - [C280669]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - await dataTable.selectMultipleItems([file1, folder1]); - 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(false, `Delete is displayed`); - expect(await contextMenu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - expect(await contextMenu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); - }); + it('on Search Results - [C297667]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions(fileLocked); + await dataTable.selectItem(fileLocked); - it('on Favorites - [C286282]', async () => { - await page.clickFavoritesAndWait(); - await dataTable.selectMultipleItems([file1, folder1]); - 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`); - // TODO: enable when ACA-1737 is done - // 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(true, `Favorite is not displayed`); - expect(await contextMenu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); - }); - }); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); - describe('toolbar actions appear correctly in the viewer - consumer', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - done(); - }); + await toolbar.openMoreMenu(); - it('file from File Libraries - [C268128]', async () => { - await page.clickFileLibrariesAndWait(); - await dataTable.doubleClickOnRowByName(siteName); - await dataTable.waitForHeader(); - await dataTable.doubleClickOnRowByName(docxFile); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - - expect(await viewerToolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); - expect(await viewerToolbar.isButtonPresent('View')).toBe(false, `View is displayed`); - expect(await viewerToolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed`); - expect(await viewerToolbar.isButtonPresent('Print')).toBe(true, `Print is not displayed`); - expect(await viewerToolbar.isButtonPresent('Activate full-screen mode')).toBe(true, `Full screen is not displayed`); - expect(await viewerToolbar.isShareEditButtonPresent()).toBe(true, 'Shared link settings is not displayed'); - expect(await viewerToolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed`); - await viewerToolbar.openMoreMenu(); - expect(await viewerToolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Share')).toBe(false, `Share is displayed in More actions`); - expect(await viewerToolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage versions is displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); - await toolbar.closeMoreMenu(); - }); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileLocked} in Search Results`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked} in Search Results`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, 'Manage versions is not displayed'); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, 'Upload new version is displayed'); - it('file from Shared Files - [C286310]', async () => { - await page.clickSharedFilesAndWait(); - await dataTable.doubleClickOnRowByName(docxFile); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - - expect(await viewerToolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); - expect(await viewerToolbar.isButtonPresent('View')).toBe(false, `View is displayed`); - expect(await viewerToolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed`); - expect(await viewerToolbar.isButtonPresent('Print')).toBe(true, `Print is not displayed`); - expect(await viewerToolbar.isButtonPresent('Activate full-screen mode')).toBe(true, `Full screen is not displayed`); - expect(await viewerToolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed`); - await viewerToolbar.openMoreMenu(); - expect(await viewerToolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage versions is displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); await toolbar.closeMoreMenu(); }); - it('file from Favorites - [C286311]', async () => { - await page.clickFavoritesAndWait(); - await dataTable.doubleClickOnRowByName(docxFile); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - - expect(await viewerToolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); - expect(await viewerToolbar.isButtonPresent('View')).toBe(false, `View is displayed`); - expect(await viewerToolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed`); - expect(await viewerToolbar.isButtonPresent('Print')).toBe(true, `Print is not displayed`); - expect(await viewerToolbar.isButtonPresent('Activate full-screen mode')).toBe(true, `Full screen is not displayed`); - expect(await viewerToolbar.isShareEditButtonPresent()).toBe(true, 'Shared link settings is not displayed'); - expect(await viewerToolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed`); - await viewerToolbar.openMoreMenu(); - expect(await viewerToolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Share')).toBe(false, `Share is displayed in More actions`); - expect(await viewerToolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`); - // TODO: enable when ACA-1737 is done - // expect(await viewerToolbar.menu.isMenuItemPresent('Move')).toBe(false, `Move is displayed`); - // expect(await viewerToolbar.menu.isMenuItemPresent('Delete')).toBe(false, `Delete is displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage versions is displayed`); - expect(await viewerToolbar.menu.isMenuItemPresent('Permissions')).toBe(false, `Permissions is displayed`); - await toolbar.closeMoreMenu(); + describe('in the viewer', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await dataTable.clearSelection(); + await page.clickPersonalFiles(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('file opened from File Libraries - [C297671]', async () => { + await page.clickFileLibrariesAndWait(); + await dataTable.doubleClickOnRowByName(siteName); + await dataTable.waitForHeader(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + + it('file opened from Shared Files - [C297672]', async () => { + await page.clickSharedFilesAndWait(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await viewerToolbar.closeMoreMenu(); + }); + + it('file opened from Favorites - [C297673]', async () => { + await page.clickFavoritesAndWait(); + await dataTable.doubleClickOnRowByName(fileLocked); + await viewer.waitForViewerToOpen(); + + expect(await viewerToolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await viewerToolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await viewerToolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await viewerToolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await viewerToolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await viewerToolbar.isSharedLinkSettingsPresent()).toBe(true, 'Shared link settings is not displayed'); + expect(await viewerToolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed`); + + await viewerToolbar.openMoreMenu(); + + expect(await viewerToolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await viewerToolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await viewerToolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await viewerToolbar.menu.isSharePresent()).toBe(false, `Share is displayed in More actions`); + expect(await viewerToolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await viewerToolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await viewerToolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await viewerToolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await viewerToolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await viewerToolbar.closeMoreMenu(); + }); }); }); }); diff --git a/e2e/suites/actions/toolbar-multiple-selection.test.ts b/e2e/suites/actions/toolbar-multiple-selection.test.ts index 3773204e6c..3ba1aaae09 100755 --- a/e2e/suites/actions/toolbar-multiple-selection.test.ts +++ b/e2e/suites/actions/toolbar-multiple-selection.test.ts @@ -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 @@ -24,7 +24,7 @@ */ import { browser, protractor } from 'protractor'; -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'; @@ -32,30 +32,29 @@ import { Utils } from '../../utilities/utils'; describe('Toolbar 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 folder1 = `folder1-${Utils.random()}`; - let folder1Id; - const folder2 = `folder2-${Utils.random()}`; - let folder2Id; - - const fileForDelete1 = `file-${Utils.random()}.txt`; - let fileForDelete1Id; - const fileForDelete2 = `file-${Utils.random()}.txt`; - let fileForDelete2Id; - const folderForDelete1 = `folder-${Utils.random()}`; - let folderForDelete1Id; - const folderForDelete2 = `folder-${Utils.random()}`; - let folderForDelete2Id; + const parent = `parent-${Utils.random()}`; let parentId; + + const file1 = `my-file1-${Utils.random()}.txt`; let file1Id; + const file2 = `my-file2-${Utils.random()}.txt`; let file2Id; + + const folder1 = `my-folder1-${Utils.random()}`; let folder1Id; + const folder2 = `my-folder2-${Utils.random()}`; let folder2Id; + + const fileForDelete1 = `file-${Utils.random()}.txt`; let fileForDelete1Id; + const fileForDelete2 = `file-${Utils.random()}.txt`; let fileForDelete2Id; + const folderForDelete1 = `folder-${Utils.random()}`; let folderForDelete1Id; + const folderForDelete2 = `folder-${Utils.random()}`; let folderForDelete2Id; const siteName = `site-${Utils.random()}`; - const file1InSite = `file1-${Utils.random()}.txt`; - const file2InSite = `file2-${Utils.random()}.txt`; - const folder1InSite = `folder1-${Utils.random()}`; - const folder2InSite = `folder2-${Utils.random()}`; + const file1InSite = `my-fileInSite1-${Utils.random()}.txt`; + const file2InSite = `my-fileInSite2-${Utils.random()}.txt`; + const folder1InSite = `my-folderInSite1-${Utils.random()}`; + const folder2InSite = `my-folderInSite2-${Utils.random()}`; + const fileLocked1InSite = `my-fileLockedInSite1-${Utils.random()}.txt`; let fileLocked1InSiteId; + const fileLocked2InSite = `my-fileLockedInSite2-${Utils.random()}.txt`; let fileLocked2InSiteId; + + const fileLocked1 = `my-fileLocked1-${Utils.random()}.txt`; let fileLocked1Id; + const fileLocked2 = `my-fileLocked2-${Utils.random()}.txt`; let fileLocked2Id; const apis = { admin: new RepoClient(), @@ -65,25 +64,33 @@ describe('Toolbar actions - multiple selection : ', () => { const loginPage = new LoginPage(); const page = new BrowsingPage(); const { dataTable, toolbar } = page; + const searchResultsPage = new SearchResultsPage(); + const { searchInput } = searchResultsPage.header; - beforeAll(async done => { + beforeAll(async (done) => { await apis.admin.people.createUser({ username }); - file1Id = (await apis.user.nodes.createFiles([file1])).entry.id; - file2Id = (await apis.user.nodes.createFiles([file2])).entry.id; - folder1Id = (await apis.user.nodes.createFolders([folder1])).entry.id; - folder2Id = (await apis.user.nodes.createFolders([folder2])).entry.id; - fileForDelete1Id = (await apis.user.nodes.createFiles([fileForDelete1])).entry.id; - fileForDelete2Id = (await apis.user.nodes.createFiles([fileForDelete2])).entry.id; - folderForDelete1Id = (await apis.user.nodes.createFolders([folderForDelete1])).entry.id; - folderForDelete2Id = (await apis.user.nodes.createFolders([folderForDelete2])).entry.id; - - await apis.user.shared.shareFilesByIds([file1Id, file2Id]); - await apis.user.shared.waitForApi({ expect: 2 }); - - await apis.user.favorites.addFavoritesByIds('file', [file1Id, file2Id]); + 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; + fileForDelete1Id = (await apis.user.nodes.createFile(fileForDelete1, parentId)).entry.id; + fileForDelete2Id = (await apis.user.nodes.createFile(fileForDelete2, parentId)).entry.id; + folderForDelete1Id = (await apis.user.nodes.createFolder(folderForDelete1, parentId)).entry.id; + folderForDelete2Id = (await apis.user.nodes.createFolder(folderForDelete2, 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.shared.shareFilesByIds([file1Id, file2Id, fileLocked1Id, fileLocked2Id]); + await apis.user.shared.waitForApi({ expect: 4 }); + + 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 }); + await apis.user.favorites.waitForApi({ expect: 6 }); await apis.user.nodes.deleteNodesById([fileForDelete1Id, fileForDelete2Id, folderForDelete1Id, folderForDelete2Id], false); await apis.user.trashcan.waitForApi({ expect: 4 }); @@ -94,35 +101,49 @@ describe('Toolbar actions - multiple selection : ', () => { await apis.user.nodes.createFile(file2InSite, docLibId); await apis.user.nodes.createFolder(folder1InSite, docLibId); await apis.user.nodes.createFolder(folder2InSite, docLibId); - await apis.user.search.waitForApi(username, { expect: 4 }); + fileLocked1InSiteId = (await apis.user.nodes.createFile(fileLocked1InSite, docLibId)).entry.id; + fileLocked2InSiteId = (await apis.user.nodes.createFile(fileLocked2InSite, docLibId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1InSiteId); + await apis.user.nodes.lockFile(fileLocked2InSiteId); + + await apis.user.search.waitForApi(username, { expect: 6 }); await loginPage.loginWith(username); done(); }); - afterAll(async done => { + afterAll(async (done) => { await Promise.all([ - apis.user.nodes.deleteNodesById([file1Id, file2Id, folder1Id, folder2Id]), + apis.user.nodes.deleteNodeById(parentId), apis.user.trashcan.emptyTrash(), apis.user.sites.deleteSite(siteName) ]); done(); }); - xit(''); - - describe('Personal Files', () => { - beforeEach(async done => { + describe('on Personal Files', () => { + beforeEach(async (done) => { await Utils.pressEscape(); - await page.clickPersonalFilesAndWait(); await dataTable.clearSelection(); + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parent); + await dataTable.waitForBody(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); it('Unselect items with single click - [C280458]', async () => { await dataTable.selectMultipleItems([file1, file2, folder1, folder2]); + expect(await dataTable.countSelectedRows()).toEqual(4, 'incorrect selected rows number'); + await dataTable.selectItem(file1); + expect(await dataTable.countSelectedRows()).toEqual(1, 'incorrect selected rows number'); }); @@ -133,7 +154,9 @@ describe('Toolbar actions - multiple selection : ', () => { await dataTable.selectItem(folder1); await dataTable.selectItem(folder2); await browser.actions().sendKeys(protractor.Key.NULL).perform(); + expect(await dataTable.countSelectedRows()).toEqual(4, 'incorrect selected rows number'); + await browser.actions().sendKeys(protractor.Key.COMMAND).perform(); await dataTable.selectItem(file1); await dataTable.selectItem(file2); @@ -144,204 +167,537 @@ describe('Toolbar actions - multiple selection : ', () => { it('correct actions appear when multiple files are selected - [C217112]', async () => { await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when multiple locked files are selected - [C297619]', async () => { + await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + await toolbar.closeMoreMenu(); }); it('correct actions appear when multiple folders are selected - [C280459]', async () => { await dataTable.selectMultipleItems([folder1, folder2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + await toolbar.closeMoreMenu(); }); it('correct actions appear when both files and folders are selected - [C280460]', async () => { await dataTable.selectMultipleItems([file1, file2, folder1, folder2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + await toolbar.closeMoreMenu(); }); }); - describe('File Libraries', () => { - beforeEach(async done => { + 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 - [C280461]', async () => { await dataTable.selectMultipleItems([file1InSite, file2InSite]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed for selected files'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed for selected files'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed for selected files'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed for selected files'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed for selected files'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed for selected files'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when multiple locked files are selected - [C297620]', async () => { + await dataTable.selectMultipleItems([fileLocked1InSite, fileLocked2InSite]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed for selected files'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed for selected files'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed for selected files'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); }); it('correct actions appear when multiple folders are selected - [C280462]', async () => { await dataTable.selectMultipleItems([folder1InSite, folder2InSite]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); }); it('correct actions appear when both files and folders are selected - [C280463]', async () => { await dataTable.selectMultipleItems([file1InSite, file2InSite, folder1InSite, folder2InSite]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); }); }); - describe('Shared Files', () => { - beforeEach(async done => { - // await browser.actions().mouseMove(browser.$('body'), { x: 0, y: 0 }).click().perform(); + describe('on Shared Files', () => { + beforeEach(async (done) => { await Utils.pressEscape(); - await page.clickSharedFilesAndWait(); await dataTable.clearSelection(); + await page.clickSharedFilesAndWait(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); it('correct actions appear when multiple files are selected - [C280467]', async () => { await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed for selected files'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed for selected files'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed for selected files'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed for selected files'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when multiple locked files are selected - [C297623]', async () => { + await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed for selected files'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed for selected files'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); }); }); - describe('Recent Files', () => { - beforeEach(async done => { + describe('on Recent Files', () => { + beforeEach(async (done) => { await Utils.pressEscape(); - await page.clickRecentFilesAndWait(); await dataTable.clearSelection(); + await page.clickRecentFilesAndWait(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); it('correct actions appear when multiple files are selected - [C280468]', async () => { await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when multiple locked files are selected - [C297624]', async () => { + await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); }); }); - describe('Favorites', () => { - beforeEach(async done => { - // await browser.actions().mouseMove(browser.$('body'), { x: 0, y: 0 }).click().perform(); + describe('on Favorites', () => { + beforeEach(async (done) => { await Utils.pressEscape(); - await page.clickFavoritesAndWait(); await dataTable.clearSelection(); + await page.clickFavoritesAndWait(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); it('correct actions appear when multiple files are selected - [C280469]', async () => { await dataTable.selectMultipleItems([file1, file2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when multiple locked files are selected - [C297625]', async () => { + await dataTable.selectMultipleItems([fileLocked1, fileLocked2]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); }); it('correct actions appear when multiple folders are selected - [C280470]', async () => { await dataTable.selectMultipleItems([folder1, folder2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); }); it('correct actions appear when both files and folders are selected - [C280471]', async () => { await dataTable.selectMultipleItems([file1, file2, folder1, folder2]); - expect(await toolbar.isButtonPresent('View')).toBe(false, 'View is displayed'); - expect(await toolbar.isButtonPresent('Download')).toBe(true, 'Download is not displayed for selected files'); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, 'Edit is displayed'); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed for selected files'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for selected files`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for selected files`); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for selected files`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); }); }); - describe('Trash', () => { - beforeEach(async done => { - await Utils.pressEscape(); + describe('on Trash', () => { + beforeEach(async (done) => { await page.clickTrashAndWait(); - await dataTable.clearSelection(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); it('correct actions appear when multiple files are selected - [C280472]', async () => { await dataTable.selectMultipleItems([fileForDelete1, fileForDelete2]); + expect(await toolbar.isButtonPresent('Permanently delete')).toBe(true, 'Permanently delete is displayed'); expect(await toolbar.isButtonPresent('Restore')).toBe(true, 'Restore is not displayed'); }); it('correct actions appear when multiple folders are selected - [C280473]', async () => { await dataTable.selectMultipleItems([folderForDelete1, folderForDelete2]); + expect(await toolbar.isButtonPresent('Permanently delete')).toBe(true, 'Permanently delete is displayed'); expect(await toolbar.isButtonPresent('Restore')).toBe(true, 'Restore is not displayed'); }); it('correct actions appear when both files and folders are selected - [C280474]', async () => { await dataTable.selectMultipleItems([fileForDelete1, fileForDelete2, folderForDelete1, folderForDelete2]); + expect(await toolbar.isButtonPresent('Permanently delete')).toBe(true, 'Permanently delete is displayed'); expect(await toolbar.isButtonPresent('Restore')).toBe(true, 'Restore is not 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 - [C291820]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions('my-fileInSite'); + await dataTable.selectMultipleItems([file1InSite, file2InSite]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed for selected files'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed for selected files'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed for selected files'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when multiple locked files are selected - [C297626]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions('my-fileLockedInSite'); + await dataTable.selectMultipleItems([fileLocked1InSite, fileLocked2InSite]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed for selected files'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed for selected files'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed for selected files'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when multiple folders are selected - [C291821]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFolders(); + await searchInput.searchForTextAndCloseSearchOptions('my-folderInSite'); + await dataTable.selectMultipleItems([folder1InSite, folder2InSite]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when both files and folders are selected - [C291822]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkFilesAndFolders(); + await searchInput.searchForTextAndCloseSearchOptions('my-f'); + await dataTable.selectMultipleItems([file1InSite, file2InSite, folder1InSite, folder2InSite]); + + expect(await toolbar.isViewPresent()).toBe(false, 'View is displayed'); + expect(await toolbar.isDownloadPresent()).toBe(true, 'Download is not displayed'); + expect(await toolbar.isEditFolderPresent()).toBe(false, 'Edit folder is displayed'); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for selected files`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for selected files`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for selected files`); + expect(await toolbar.menu.isToggleFavoritePresent()).toBe(true, `Favorite is not displayed for selected files`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed`); + + await toolbar.closeMoreMenu(); + }); + }); }); diff --git a/e2e/suites/actions/toolbar-single-selection.test.ts b/e2e/suites/actions/toolbar-single-selection.test.ts index 607b01c921..1119da4911 100755 --- a/e2e/suites/actions/toolbar-single-selection.test.ts +++ b/e2e/suites/actions/toolbar-single-selection.test.ts @@ -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 . */ -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,10 +35,12 @@ describe('Toolbar actions - single selection : ', () => { const folderUser = `folderUser-${Utils.random()}`; let folderUserId; const fileForDelete = `fileForDelete-${Utils.random()}.txt`; let fileForDeleteId; const folderForDelete = `folderForDelete-${Utils.random()}`; let folderForDeleteId; + const fileLocked = `fileLocked-${Utils.random()}.txt`; let fileLockedId; const siteName = `site-${Utils.random()}`; - const fileInSite = `fileAdmin-${Utils.random()}.txt`; - const folderInSite = `folderAdmin-${Utils.random()}`; + const fileInSite = `file-site-${Utils.random()}.txt`; + const fileLockedInSite = `file-locked-site-${Utils.random()}.txt`; let fileLockedInSiteId; + const folderInSite = `folder-site-${Utils.random()}`; const adminPublic = `admin-public-${Utils.random()}`; const adminModerated = `admin-moderated-${Utils.random()}`; @@ -51,6 +53,8 @@ describe('Toolbar actions - single selection : ', () => { const loginPage = new LoginPage(); const page = new BrowsingPage(); const { dataTable, toolbar } = page; + const searchResultsPage = new SearchResultsPage(); + const { searchInput } = searchResultsPage.header; beforeAll(async (done) => { await apis.admin.people.createUser({ username }); @@ -59,19 +63,27 @@ describe('Toolbar actions - single selection : ', () => { fileForDeleteId = (await apis.user.nodes.createFile(fileForDelete)).entry.id; folderForDeleteId = (await apis.user.nodes.createFolder(folderForDelete)).entry.id; folderUserId = (await apis.user.nodes.createFolder(folderUser)).entry.id; + fileLockedId = (await apis.user.nodes.createFile(fileLocked)).entry.id; 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('folder', folderUserId); - await apis.user.favorites.waitForApi({ expect: 2 }); + await apis.user.favorites.addFavoriteById('file', fileLockedId); + await apis.user.favorites.waitForApi({ expect: 3 }); + + await apis.user.nodes.lockFile(fileLockedId); await apis.user.sites.createSite(siteName, SITE_VISIBILITY.PRIVATE); const docLibId = await apis.user.sites.getDocLibId(siteName); await apis.user.nodes.createFile(fileInSite, docLibId); + fileLockedInSiteId = (await apis.user.nodes.createFile(fileLockedInSite, docLibId)).entry.id; await apis.user.nodes.createFolder(folderInSite, docLibId); + await apis.user.nodes.lockFile(fileLockedInSiteId); + await apis.user.nodes.deleteNodeById(fileForDeleteId, false); await apis.user.nodes.deleteNodeById(folderForDeleteId, false); @@ -81,6 +93,8 @@ describe('Toolbar 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 loginPage.loginWith(username); done(); }); @@ -97,28 +111,23 @@ describe('Toolbar actions - single selection : ', () => { done(); }); - xit(''); - - describe('General tests', () => { + describe('on Personal Files', () => { beforeEach(async (done) => { await Utils.pressEscape(); await dataTable.clearSelection(); + await page.clickPersonalFilesAndWait(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); it('selected row is marked with a check circle icon - [C213134]', async () => { - await page.clickPersonalFilesAndWait(); await dataTable.selectItem(fileUser); - expect(await dataTable.hasCheckMarkIcon(fileUser)).toBe(true, 'check mark missing'); - }); - }); - describe('on Personal Files', () => { - beforeEach(async (done) => { - await Utils.pressEscape(); - await page.clickPersonalFilesAndWait(); - await dataTable.clearSelection(); - done(); + expect(await dataTable.hasCheckMarkIcon(fileUser)).toBe(true, 'check mark missing'); }); it('actions are not displayed when no item is selected - [C213120]', async () => { @@ -127,29 +136,67 @@ describe('Toolbar actions - single selection : ', () => { it('correct actions appear when a file is selected - [C213122]', async () => { await dataTable.selectItem(fileUser); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${fileUser}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileUser}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload New Version is not displayed for ${fileUser}`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when a locked file is selected - [C297612]', async () => { + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); + await toolbar.closeMoreMenu(); }); it('correct actions appear when a folder is selected - [C213123]', async () => { await dataTable.selectItem(folderUser); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${folderUser}`); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for ${folderUser}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not enabled for ${folderUser}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(true, `Edit is not displayed for ${folderUser}`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for ${folderUser}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not enabled for ${folderUser}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderUser}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderUser}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderUser}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderUser}`); + + expect(await toolbar.menu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderUser}`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderUser}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderUser}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folderUser}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${folderUser}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${folderUser}`); + expect(await toolbar.menu.isRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folderUser}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folderUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`); + await toolbar.closeMoreMenu(); }); }); @@ -157,10 +204,14 @@ describe('Toolbar actions - single selection : ', () => { 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(); }); @@ -170,29 +221,67 @@ describe('Toolbar actions - single selection : ', () => { it('correct actions appear when a file is selected - [C280440]', async () => { await dataTable.selectItem(fileInSite); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileInSite}`); - expect(await toolbar.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileInSite}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileInSite}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileInSite}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileInSite}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileInSite}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileInSite}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileInSite}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileInSite}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileInSite}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileInSite}`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${fileInSite}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileInSite}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileInSite}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileInSite}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileInSite}`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileInSite}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileInSite}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileInSite}`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when a locked file is selected - [C297614]', async () => { + await dataTable.selectItem(fileLockedInSite); + + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLockedInSite}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLockedInSite}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLockedInSite}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLockedInSite}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLockedInSite}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLockedInSite}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLockedInSite}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLockedInSite}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLockedInSite}`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${fileLockedInSite}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLockedInSite}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLockedInSite}`); + await toolbar.closeMoreMenu(); }); it('correct actions appear when a folder is selected - [C280441]', async () => { await dataTable.selectItem(folderInSite); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${folderInSite}`); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for ${folderInSite}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not enabled for ${folderInSite}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(true, `Edit is not displayed for ${folderInSite}`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for ${folderInSite}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not enabled for ${folderInSite}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderInSite}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderInSite}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderInSite}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderInSite}`); + + expect(await toolbar.menu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderInSite}`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderInSite}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderInSite}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folderInSite}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${folderInSite}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${folderInSite}`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed for ${folderInSite}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folderInSite}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderInSite}`); + await toolbar.closeMoreMenu(); }); }); @@ -200,52 +289,131 @@ describe('Toolbar actions - single selection : ', () => { describe('on a library', () => { beforeEach(async (done) => { await Utils.pressEscape(); - await dataTable.clearSelection(); done(); }); - it('Available actions when a library is selected - My Libraries - [C213135]', async () => { - await page.goToMyLibraries(); + afterAll(async (done) => { + await Utils.pressEscape(); + await page.clickPersonalFiles(); + done(); + }); + + it('Available actions for a library - My Libraries - [C213135]', async () => { + await page.goToMyLibrariesAndWait(); await dataTable.selectItem(siteName); + expect(await toolbar.isEmpty()).toBe(false, 'toolbar not displayed'); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${siteName}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${siteName}`); expect(await toolbar.isButtonPresent('Leave library')).toBe(true, `Leave is not displayed for ${siteName}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${siteName}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${siteName}`); + + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${siteName}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${siteName}`); + + await toolbar.closeMoreMenu(); }); - it('Available actions when a library is selected - Favorite Libraries - user is a member - [C289892]', async () => { - await page.goToFavoriteLibraries(); + it('Available actions for a library - Favorite Libraries - user is a member - [C289892]', async () => { + await page.goToFavoriteLibrariesAndWait(); await dataTable.selectItem(siteName); + expect(await toolbar.isEmpty()).toBe(false, 'toolbar not displayed'); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${siteName}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${siteName}`); expect(await toolbar.isButtonPresent('Leave library')).toBe(true, `Leave is not displayed for ${siteName}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${siteName}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${siteName}`); + + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${siteName}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${siteName}`); + + await toolbar.closeMoreMenu(); }); - it('Available actions when a library is selected - Favorite Libraries - user is not a member - [C290090]', async () => { - await page.goToFavoriteLibraries(); + it('Available actions for a library - Favorite Libraries - user is not a member - [C290090]', async () => { + await page.goToFavoriteLibrariesAndWait(); await dataTable.selectItem(adminPublic); + expect(await toolbar.isEmpty()).toBe(false, 'toolbar not displayed'); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${adminPublic}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${adminPublic}`); expect(await toolbar.isButtonPresent('Join')).toBe(true, `Join is not displayed for ${adminPublic}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${adminPublic}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${adminPublic}`); + + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${adminPublic}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${adminPublic}`); + + await toolbar.closeMoreMenu(); + }); + + it('Available actions for a moderated library - Favorite Libraries - user requested to join - [C290091]', async () => { + await page.goToFavoriteLibrariesAndWait(); + await dataTable.selectItem(adminModerated); + + expect(await toolbar.isEmpty()).toBe(false, 'toolbar not displayed'); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${adminModerated}`); + expect(await toolbar.isButtonPresent('Cancel join request')).toBe(true, `Cancel join is not displayed for ${adminModerated}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${adminModerated}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${adminModerated}`); + + await toolbar.closeMoreMenu(); + }); + + it('Available actions for a library - Search Results - [C290084]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkLibraries(); + await searchInput.searchForTextAndCloseSearchOptions(siteName); + await dataTable.selectItem(siteName); + + expect(await toolbar.isEmpty()).toBe(false, 'toolbar not displayed'); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${siteName}`); + expect(await toolbar.isButtonPresent('Leave library')).toBe(true, `Leave is not displayed for ${siteName}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${siteName}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${siteName}`); + + await toolbar.closeMoreMenu(); + }); + + it('Available actions for a library - Search Results - user is not a member - [C290085]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkLibraries(); + await searchInput.searchForTextAndCloseSearchOptions(adminPublic); + await dataTable.selectItem(adminPublic); + + expect(await toolbar.isEmpty()).toBe(false, 'toolbar not displayed'); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${adminPublic}`); + expect(await toolbar.isButtonPresent('Join')).toBe(true, `Join is not displayed for ${adminPublic}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${adminPublic}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${adminPublic}`); + + await toolbar.closeMoreMenu(); }); - it('Available actions when a library is selected - Favorite Libraries - user requested to join - [C290091]', async () => { - await page.goToFavoriteLibraries(); + it('Available actions for a moderated library - Search Results - user requested to join - [C290086]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkLibraries(); + await searchInput.searchForTextAndCloseSearchOptions(adminModerated); await dataTable.selectItem(adminModerated); + expect(await toolbar.isEmpty()).toBe(false, 'toolbar not displayed'); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `View details is not displayed for ${adminModerated}`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `View details is not displayed for ${adminModerated}`); expect(await toolbar.isButtonPresent('Cancel join request')).toBe(true, `Cancel join is not displayed for ${adminModerated}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${adminModerated}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${adminModerated}`); + + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${adminModerated}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${adminModerated}`); + + await toolbar.closeMoreMenu(); }); }); @@ -253,7 +421,11 @@ describe('Toolbar actions - single selection : ', () => { beforeEach(async (done) => { await Utils.pressEscape(); await page.clickSharedFilesAndWait(); - await dataTable.clearSelection(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); @@ -263,16 +435,49 @@ describe('Toolbar actions - single selection : ', () => { it('correct actions appear when a file is selected - [C286265]', async () => { await page.dataTable.selectItem(fileUser); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`); - expect(await toolbar.isShareEditButtonPresent()).toBe(true, `Shared link settings is not displayed for ${fileUser}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed for ${fileUser}`); + + await toolbar.openMoreMenu(); + + // TODO: change expect to true when ACA-2173 is done + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileUser}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileUser}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when a locked file is selected - [C297615]', async () => { + await page.dataTable.selectItem(fileLocked); + + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed for ${fileLocked}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + // TODO: change expect to true when ACA-2173 is done + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); + await toolbar.closeMoreMenu(); }); }); @@ -281,7 +486,11 @@ describe('Toolbar actions - single selection : ', () => { beforeEach(async (done) => { await Utils.pressEscape(); await page.clickRecentFilesAndWait(); - await dataTable.clearSelection(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); @@ -291,15 +500,45 @@ describe('Toolbar actions - single selection : ', () => { it('correct actions appear when a file is selected - [C280448]', async () => { await dataTable.selectItem(fileUser); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${fileUser}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileUser}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when a locked file is selected - [C297616]', async () => { + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); + await toolbar.closeMoreMenu(); }); }); @@ -308,7 +547,11 @@ describe('Toolbar actions - single selection : ', () => { beforeEach(async (done) => { await Utils.pressEscape(); await page.clickFavoritesAndWait(); - await dataTable.clearSelection(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); @@ -318,29 +561,69 @@ describe('Toolbar actions - single selection : ', () => { it('correct actions appear when a file is selected - [C280450]', async () => { await dataTable.selectItem(fileUser); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('View')).toBe(true, `View is not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed for ${fileUser}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(false, `Edit is displayed for ${fileUser}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); + + await toolbar.openMoreMenu(); + + // TODO: change expect to true when ACA-2174 is done + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileUser}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileUser}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileUser}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileUser}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when a locked file is selected - [C297617]', async () => { + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${fileUser}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${fileUser}`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + // TODO: change expect to true when ACA-2174 is done + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); + await toolbar.closeMoreMenu(); }); it('correct actions appear when a folder is selected - [C280451]', async () => { await dataTable.selectItem(folderUser); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${folderUser}`); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed for ${folderUser}`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not enabled for ${folderUser}`); - expect(await toolbar.isButtonPresent('Edit')).toBe(true, `Edit is not displayed for ${folderUser}`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for ${folderUser}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not enabled for ${folderUser}`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed for ${folderUser}`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed for ${folderUser}`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed for ${folderUser}`); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed for ${folderUser}`); + + expect(await toolbar.menu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderUser}`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderUser}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderUser}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folderUser}`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed for ${folderUser}`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed for ${folderUser}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folderUser}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folderUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`); + await toolbar.closeMoreMenu(); }); }); @@ -349,7 +632,11 @@ describe('Toolbar actions - single selection : ', () => { beforeEach(async (done) => { await Utils.pressEscape(); await page.clickTrashAndWait(); - await dataTable.clearSelection(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); done(); }); @@ -359,16 +646,115 @@ describe('Toolbar actions - single selection : ', () => { it('correct actions appear when a file is selected - [C280453]', async () => { await dataTable.selectItem(fileForDelete); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileForDelete}`); - expect(await toolbar.isButtonPresent('Permanently delete')).toBe(true, `Permanently delete is not displayed for file`); - expect(await toolbar.isButtonPresent('Restore')).toBe(true, `Restore is not displayed for file`); + expect(await toolbar.isPermanentlyDeletePresent()).toBe(true, `Permanently delete is not displayed for file`); + expect(await toolbar.isRestorePresent()).toBe(true, `Restore is not displayed for file`); }); it('correct actions appear when a folder is selected - [C280454]', async () => { await dataTable.selectItem(folderForDelete); + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${folderForDelete}`); - expect(await toolbar.isButtonPresent('Permanently delete')).toBe(true, `Permanently delete is displayed for folder`); - expect(await toolbar.isButtonPresent('Restore')).toBe(true, `Restore is not enabled for folder`); + expect(await toolbar.isPermanentlyDeletePresent()).toBe(true, `Permanently delete is displayed for folder`); + expect(await toolbar.isRestorePresent()).toBe(true, `Restore is not displayed for folder`); + }); + }); + + describe('on Search Results', () => { + beforeEach(async (done) => { + await Utils.pressEscape(); + await page.clickPersonalFilesAndWait(); + done(); + }); + + afterAll(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('nodes actions are not displayed when no item is selected - [C291815]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkFilesAndFolders(); + await searchInput.searchForTextAndCloseSearchOptions(fileInSite); + + expect(await toolbar.isToggleSearchFiltersPresent()).toBe(true, `Search filter toggle is not displayed`); + expect(await toolbar.numberOfAvailableActions()).toBe(1, `more than 1 action is present`); + }); + + it('correct actions appear when a file is selected - [C291816]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions(fileUser); + await dataTable.selectItem(fileUser); + + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileUser}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileUser}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileUser}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileUser}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed for ${fileUser}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${fileUser}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileUser}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileUser}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileUser}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileUser}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileUser}`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when a locked file is selected - [C297618]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFiles(); + await searchInput.searchForTextAndCloseSearchOptions(fileLocked); + await dataTable.selectItem(fileLocked); + + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${fileLocked}`); + expect(await toolbar.isViewPresent()).toBe(true, `View is not displayed for ${fileLocked}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed for ${fileLocked}`); + expect(await toolbar.isEditFolderPresent()).toBe(false, `Edit folder is displayed for ${fileLocked}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${fileLocked}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${fileLocked}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${fileLocked}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed for ${fileLocked}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed for ${fileLocked}`); + + await toolbar.closeMoreMenu(); + }); + + it('correct actions appear when a folder is selected - [C291817]', async () => { + await searchInput.clickSearchButton(); + await searchInput.checkOnlyFolders(); + await searchInput.searchForTextAndCloseSearchOptions(folderUser); + await dataTable.selectItem(folderUser); + + expect(await toolbar.isEmpty()).toBe(false, `actions not displayed for ${folderUser}`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed for ${folderUser}`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not enabled for ${folderUser}`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditFolderPresent()).toBe(true, `Edit folder is not displayed for ${folderUser}`); + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed for ${folderUser}`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed for ${folderUser}`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed for ${folderUser}`); + expect(await toolbar.menu.isDeletePresent()).toBe(false, `Delete is displayed for ${folderUser}`); + expect(await toolbar.menu.isMovePresent()).toBe(false, `Move is displayed for ${folderUser}`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed for ${folderUser}`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(false, `Manage versions is displayed for ${folderUser}`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(false, `Upload new version is displayed for ${folderUser}`); + + await toolbar.closeMoreMenu(); }); }); }); diff --git a/e2e/suites/actions/unshare-file.test.ts b/e2e/suites/actions/unshare-file.test.ts index 34e6781cf3..dee4dc7f9d 100755 --- a/e2e/suites/actions/unshare-file.test.ts +++ b/e2e/suites/actions/unshare-file.test.ts @@ -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 @@ -106,7 +106,7 @@ describe('Unshare a file', () => { it('Unshare dialog UI - [C286339]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); @@ -115,18 +115,18 @@ describe('Unshare a file', () => { expect(await confirmDialog.isDialogOpen()).toBe(true, 'Unshare dialog is not open'); expect(await confirmDialog.getTitle()).toContain('Remove this shared link'); expect(await confirmDialog.getText()).toContain('This link will be deleted and a new link will be created next time this file is shared'); - expect(await confirmDialog.isButtonEnabled('Remove')).toBe(true, 'REMOVE button is not enabled'); - expect(await confirmDialog.isButtonEnabled('Cancel')).toBe(true, 'CANCEL button is not enabled'); + expect(await confirmDialog.isRemoveEnabled()).toBe(true, 'REMOVE button is not enabled'); + expect(await confirmDialog.isCancelEnabled()).toBe(true, 'CANCEL button is not enabled'); }); it('Unshare a file - [C286340]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); @@ -134,7 +134,7 @@ describe('Unshare a file', () => { // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file2).isPresent()).toBe(false, `${file2} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file2)).toBe(false, `${file2} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -145,13 +145,13 @@ describe('Unshare a file', () => { it('Cancel the Unshare action - [C286341]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const urlBefore = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Cancel'); + await confirmDialog.clickCancel(); await confirmDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Share dialog not open'); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle is off'); @@ -162,12 +162,12 @@ describe('Unshare a file', () => { it('Unshare a file from the context menu - [C286359]', async () => { await dataTable.rightClickOnItem(file4); - await contextMenu.clickShareEditAction(); + await contextMenu.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); @@ -175,7 +175,7 @@ describe('Unshare a file', () => { // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file4).isPresent()).toBe(false, `${file4} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file4)).toBe(false, `${file4} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -214,7 +214,7 @@ describe('Unshare a file', () => { beforeEach(async (done) => { await page.refresh(); - await page.clickFileLibrariesAndWait(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); await dataTable.doubleClickOnRowByName(parentInSite); @@ -235,7 +235,7 @@ describe('Unshare a file', () => { it('Unshare dialog UI - [C286679]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); @@ -244,18 +244,18 @@ describe('Unshare a file', () => { expect(await confirmDialog.isDialogOpen()).toBe(true, 'Unshare dialog is not open'); expect(await confirmDialog.getTitle()).toContain('Remove this shared link'); expect(await confirmDialog.getText()).toContain('This link will be deleted and a new link will be created next time this file is shared'); - expect(await confirmDialog.isButtonEnabled('Remove')).toBe(true, 'REMOVE button is not enabled'); - expect(await confirmDialog.isButtonEnabled('Cancel')).toBe(true, 'CANCEL button is not enabled'); + expect(await confirmDialog.isRemoveEnabled()).toBe(true, 'REMOVE button is not enabled'); + expect(await confirmDialog.isCancelEnabled()).toBe(true, 'CANCEL button is not enabled'); }); it('Unshare a file - [C286680]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); @@ -263,7 +263,7 @@ describe('Unshare a file', () => { // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file2).isPresent()).toBe(false, `${file2} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file2)).toBe(false, `${file2} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -274,13 +274,13 @@ describe('Unshare a file', () => { it('Cancel the Unshare action - [C286681]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const urlBefore = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Cancel'); + await confirmDialog.clickCancel(); await confirmDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Share dialog not open'); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle is off'); @@ -291,12 +291,12 @@ describe('Unshare a file', () => { it('Unshare a file from the context menu - [C286683]', async () => { await dataTable.rightClickOnItem(file4); - await contextMenu.clickShareEditAction(); + await contextMenu.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); @@ -304,7 +304,7 @@ describe('Unshare a file', () => { // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file4).isPresent()).toBe(false, `${file4} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file4)).toBe(false, `${file4} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -356,7 +356,7 @@ describe('Unshare a file', () => { it('Unshare dialog UI - [C286689]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); @@ -365,18 +365,18 @@ describe('Unshare a file', () => { expect(await confirmDialog.isDialogOpen()).toBe(true, 'Unshare dialog is not open'); expect(await confirmDialog.getTitle()).toContain('Remove this shared link'); expect(await confirmDialog.getText()).toContain('This link will be deleted and a new link will be created next time this file is shared'); - expect(await confirmDialog.isButtonEnabled('Remove')).toBe(true, 'REMOVE button is not enabled'); - expect(await confirmDialog.isButtonEnabled('Cancel')).toBe(true, 'CANCEL button is not enabled'); + expect(await confirmDialog.isRemoveEnabled()).toBe(true, 'REMOVE button is not enabled'); + expect(await confirmDialog.isCancelEnabled()).toBe(true, 'CANCEL button is not enabled'); }); it('Unshare a file - [C286690]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); @@ -384,7 +384,7 @@ describe('Unshare a file', () => { // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file2).isPresent()).toBe(false, `${file2} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file2)).toBe(false, `${file2} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -395,13 +395,13 @@ describe('Unshare a file', () => { it('Cancel the Unshare action - [C286691]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const urlBefore = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Cancel'); + await confirmDialog.clickCancel(); await confirmDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Share dialog not open'); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle is off'); @@ -412,12 +412,12 @@ describe('Unshare a file', () => { it('Unshare a file from the context menu - [C286693]', async () => { await dataTable.rightClickOnItem(file4); - await contextMenu.clickShareEditAction(); + await contextMenu.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); @@ -425,7 +425,7 @@ describe('Unshare a file', () => { // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file4).isPresent()).toBe(false, `${file4} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file4)).toBe(false, `${file4} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -477,7 +477,7 @@ describe('Unshare a file', () => { it('Unshare dialog UI - [C286684]', async () => { await dataTable.selectItem(file1); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); @@ -486,25 +486,25 @@ describe('Unshare a file', () => { expect(await confirmDialog.isDialogOpen()).toBe(true, 'Unshare dialog is not open'); expect(await confirmDialog.getTitle()).toContain('Remove this shared link'); expect(await confirmDialog.getText()).toContain('This link will be deleted and a new link will be created next time this file is shared'); - expect(await confirmDialog.isButtonEnabled('Remove')).toBe(true, 'REMOVE button is not enabled'); - expect(await confirmDialog.isButtonEnabled('Cancel')).toBe(true, 'CANCEL button is not enabled'); + expect(await confirmDialog.isRemoveEnabled()).toBe(true, 'REMOVE button is not enabled'); + expect(await confirmDialog.isCancelEnabled()).toBe(true, 'CANCEL button is not enabled'); }); it('Unshare a file - [C286685]', async () => { await dataTable.selectItem(file2); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); expect(await apis.user.nodes.isFileShared(file2Id)).toBe(false, `${file2} is shared`); // TODO: disable check cause api is slow to update - // expect(await dataTable.getRowByName(file2).isPresent()).toBe(false, `${file2} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file2)).toBe(false, `${file2} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -515,13 +515,13 @@ describe('Unshare a file', () => { it('Cancel the Unshare action - [C286686]', async () => { await dataTable.selectItem(file3); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const urlBefore = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Cancel'); + await confirmDialog.clickCancel(); await confirmDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Share dialog not open'); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle is off'); @@ -532,19 +532,19 @@ describe('Unshare a file', () => { it('Unshare a file from the context menu - [C286688]', async () => { await dataTable.rightClickOnItem(file4); - await contextMenu.clickShareEditAction(); + await contextMenu.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); expect(await apis.user.nodes.isFileShared(file4Id)).toBe(false, `${file4} is shared`); // TODO: disable check cause api is slow to update - // expect(await dataTable.getRowByName(file4).isPresent()).toBe(false, `${file4} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file4)).toBe(false, `${file4} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -604,8 +604,8 @@ describe('Unshare a file', () => { it('Unshare dialog UI - [C286694]', async () => { await dataTable.selectItem(file1); // TODO: remove workaround for favorites - // await toolbar.clickShareEditButton(); - await toolbar.clickShareButton(); + // await toolbar.clickSharedLinkSettings(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle not checked'); @@ -614,20 +614,20 @@ describe('Unshare a file', () => { expect(await confirmDialog.isDialogOpen()).toBe(true, 'Unshare dialog is not open'); expect(await confirmDialog.getTitle()).toContain('Remove this shared link'); expect(await confirmDialog.getText()).toContain('This link will be deleted and a new link will be created next time this file is shared'); - expect(await confirmDialog.isButtonEnabled('Remove')).toBe(true, 'REMOVE button is not enabled'); - expect(await confirmDialog.isButtonEnabled('Cancel')).toBe(true, 'CANCEL button is not enabled'); + expect(await confirmDialog.isRemoveEnabled()).toBe(true, 'REMOVE button is not enabled'); + expect(await confirmDialog.isCancelEnabled()).toBe(true, 'CANCEL button is not enabled'); }); it('Unshare a file - [C286695]', async () => { await dataTable.selectItem(file2); // TODO: remove workaround for favorites - // await toolbar.clickShareEditButton(); - await toolbar.clickShareButton(); + // await toolbar.clickSharedLinkSettings(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); @@ -635,7 +635,7 @@ describe('Unshare a file', () => { // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file2).isPresent()).toBe(false, `${file2} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file2)).toBe(false, `${file2} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -647,14 +647,14 @@ describe('Unshare a file', () => { it('Cancel the Unshare action - [C286696]', async () => { await dataTable.selectItem(file3); // TODO: remove workaround for favorites - // await toolbar.clickShareEditButton(); - await toolbar.clickShareButton(); + // await toolbar.clickSharedLinkSettings(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); const urlBefore = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Cancel'); + await confirmDialog.clickCancel(); await confirmDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Share dialog not open'); expect(await shareDialog.isShareToggleChecked()).toBe(true, 'Share toggle is off'); @@ -666,13 +666,13 @@ describe('Unshare a file', () => { it('Unshare a file from the context menu - [C286698]', async () => { await dataTable.rightClickOnItem(file4); // TODO: remove workaround for favorites - // await toolbar.clickShareEditButton(); - await contextMenu.clickShareAction(); + // await toolbar.clickSharedLinkSettings(); + await contextMenu.clickShare(); await shareDialog.waitForDialogToOpen(); const url = await shareDialog.getLinkUrl(); await shareDialog.clickShareToggle(); - await confirmDialog.clickButton('Remove'); + await confirmDialog.clickRemove(); await confirmDialog.waitForDialogToClose(); await shareDialog.waitForDialogToClose(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Share dialog open'); @@ -680,7 +680,7 @@ describe('Unshare a file', () => { // TODO: disable check cause api is slow to update // await page.clickSharedFiles(); - // expect(await dataTable.getRowByName(file4).isPresent()).toBe(false, `${file4} is in the Shared files list`); + // expect(await dataTable.isItemPresent(file4)).toBe(false, `${file4} is in the Shared files list`); await browser.get(url); expect(await viewer.isViewerOpened()).toBe(true, 'viewer is not open'); @@ -733,22 +733,22 @@ describe('Unshare a file', () => { }); it('on File Libraries - file shared by other user - [C286682]', async () => { - await page.clickFileLibrariesAndWait(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(sitePrivate); await dataTable.waitForHeader(); await dataTable.selectItem(file1); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleDisabled()).toBe(false, 'Share toggle enabled for consumer'); }); it('on File Libraries - file shared by the user - [C286701]', async () => { - await page.clickFileLibrariesAndWait(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(sitePrivate); await dataTable.waitForHeader(); await dataTable.selectItem(file2); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleDisabled()).toBe(false, 'Share toggle enabled for consumer'); @@ -757,7 +757,7 @@ describe('Unshare a file', () => { it('on Shared Files - file shared by other user - [C286687]', async () => { await page.clickSharedFilesAndWait(); await dataTable.selectItem(file1); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleDisabled()).toBe(false, 'Share toggle enabled for consumer'); @@ -766,7 +766,7 @@ describe('Unshare a file', () => { it('on Shared Files - file shared by the user - [C286702]', async () => { await page.clickSharedFilesAndWait(); await dataTable.selectItem(file1); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleDisabled()).toBe(false, 'Share toggle enabled for consumer'); @@ -776,8 +776,8 @@ describe('Unshare a file', () => { await page.clickFavoritesAndWait(); await dataTable.selectItem(file1); // TODO: remove workaround for favorites - // await toolbar.clickShareEditButton(); - await toolbar.clickShareButton(); + // await toolbar.clickSharedLinkSettings(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleDisabled()).toBe(false, 'Share toggle enabled for consumer'); @@ -787,13 +787,12 @@ describe('Unshare a file', () => { await page.clickFavoritesAndWait(); await dataTable.selectItem(file1); // TODO: remove workaround for favorites - // await toolbar.clickShareEditButton(); - await toolbar.clickShareButton(); + // await toolbar.clickSharedLinkSettings(); + await toolbar.clickShare(); await shareDialog.waitForDialogToOpen(); expect(await shareDialog.isShareToggleDisabled()).toBe(false, 'Share toggle enabled for consumer'); }); }); - xit(''); }); diff --git a/e2e/suites/actions/upload-file.test.ts b/e2e/suites/actions/upload-file.test.ts index e444582271..b99a54c43f 100755 --- a/e2e/suites/actions/upload-file.test.ts +++ b/e2e/suites/actions/upload-file.test.ts @@ -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 diff --git a/e2e/suites/actions/upload-new-version.test.ts b/e2e/suites/actions/upload-new-version.test.ts new file mode 100755 index 0000000000..955005ee77 --- /dev/null +++ b/e2e/suites/actions/upload-new-version.test.ts @@ -0,0 +1,672 @@ +/*! + * @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 . + */ + +import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { FILES } from '../../configs'; +import { RepoClient } from '../../utilities/repo-client/repo-client'; +import { Utils } from '../../utilities/utils'; +import { UploadNewVersionDialog } from '../../components/dialog/upload-new-version-dialog'; + +describe('Upload new version', () => { + const username = `user-${Utils.random()}`; + + const file1 = `file1-${Utils.random()}.docx`; let file1Id; + const file2 = `file2-${Utils.random()}.docx`; let file2Id; + const file3 = `file3-${Utils.random()}.docx`; let file3Id; + const file4 = `file4-${Utils.random()}.docx`; let file4Id; + const fileLocked1 = `file-locked1-${Utils.random()}.docx`; let fileLocked1Id; + const fileLocked2 = `file-locked2-${Utils.random()}.docx`; let fileLocked2Id; + + const parentPF = `parentPersonal-${Utils.random()}`; let parentPFId; + const parentSF = `parentShared-${Utils.random()}`; let parentSFId; + const parentRF = `parentRecent-${Utils.random()}`; let parentRFId; + const parentFav = `parentFav-${Utils.random()}`; let parentFavId; + + const file = FILES.pdfFile; let fileId; + const fileToUpload1 = FILES.docxFile; + const fileToUpload2 = FILES.xlsxFile; + const fileToUpload3 = FILES.pdfFile; + const fileToUpload4 = FILES.docxFile2; + const fileToUpload5 = FILES.xlsxFile2; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable, toolbar } = page; + const uploadNewVersionDialog = new UploadNewVersionDialog(); + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + + parentPFId = (await apis.user.nodes.createFolder(parentPF)).entry.id; + parentSFId = (await apis.user.nodes.createFolder(parentSF)).entry.id; + parentRFId = (await apis.user.nodes.createFolder(parentRF)).entry.id; + parentFavId = (await apis.user.nodes.createFolder(parentFav)).entry.id; + + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentPFId); + await apis.user.nodes.deleteNodeById(parentSFId); + await apis.user.nodes.deleteNodeById(parentRFId); + await apis.user.nodes.deleteNodeById(parentFavId); + done(); + }); + + describe('on Personal Files', () => { + beforeAll(async (done) => { + fileId = (await apis.user.upload.uploadFile(file, parentPFId)).entry.id; + file1Id = (await apis.user.nodes.createFile(file1, parentPFId)).entry.id; + file2Id = (await apis.user.nodes.createFile(file2, parentPFId)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, parentPFId)).entry.id; + file4Id = (await apis.user.nodes.createFile(file4, parentPFId)).entry.id; + + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentPFId)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentPFId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked2Id); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parentPF); + done(); + }); + + afterEach(async (done) => { + // await Utils.pressEscape(); + await page.refresh(); + done(); + }); + + it('dialog UI defaults - [C297544]', async () => { + await dataTable.selectItem(file); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version'); + expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?'); + expect(await uploadNewVersionDialog.isDescriptionDisplayed()).toBe(true, 'Description not displayed'); + expect(await uploadNewVersionDialog.isMinorOptionDisplayed()).toBe(true, 'Minor option not displayed'); + expect(await uploadNewVersionDialog.isMajorOptionDisplayed()).toBe(true, 'Major option not displayed'); + expect(await uploadNewVersionDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await uploadNewVersionDialog.isUploadButtonEnabled()).toBe(true, 'Update button not enabled'); + }); + + it('file is updated after uploading a new version - major - [C297545]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload1)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file1Id)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file1Id)).toEqual('1.0', 'File has incorrect version label'); + }); + + it('file is updated after uploading a new version - minor - [C297546]', async () => { + await dataTable.selectItem(file2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new minor version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload2)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file2Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file2Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file is not updated when clicking Cancel - [C297547]', async () => { + await dataTable.selectItem(file3); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload3); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(file3)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file3Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file3Id)).toEqual('', 'File has incorrect version label'); + }); + + it('upload new version fails when new file name already exists - [C297548]', async () => { + await dataTable.selectItem(file4); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(file); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + await page.refresh(); + + expect(await dataTable.isItemPresent(file4)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file4Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file4Id)).toEqual('', 'File has incorrect version label'); + }); + + it('file is unlocked after uploading a new version - [C297549]', async () => { + await dataTable.selectItem(fileLocked1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload4); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload4)).toBe(true, 'File name was not changed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked1Id)).toBe(false, `${fileLocked1} is still locked`); + expect(await apis.user.nodes.getFileVersionType(fileLocked1Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLocked1Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file remains locked after canceling of uploading a new version - [C297550]', async () => { + await dataTable.selectItem(fileLocked2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload5); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(fileToUpload5)).toBe(false, 'File was updated'); + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, 'File not displayed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked2Id)).toBe(true, `${fileLocked2} was unlocked`); + }); + }); + + describe('on Shared Files', () => { + beforeAll(async (done) => { + fileId = (await apis.user.upload.uploadFile(file, parentSFId)).entry.id; + file1Id = (await apis.user.nodes.createFile(file1, parentSFId)).entry.id; + file2Id = (await apis.user.nodes.createFile(file2, parentSFId)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, parentSFId)).entry.id; + file4Id = (await apis.user.nodes.createFile(file4, parentSFId)).entry.id; + + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentSFId)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentSFId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.shared.shareFilesByIds([fileId, file1Id, file2Id, file3Id, file4Id, fileLocked1Id, fileLocked2Id]); + await apis.user.shared.waitForApi({ expect: 7 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickSharedFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + // await Utils.pressEscape(); + await page.refresh(); + done(); + }); + + it('dialog UI defaults - [C297551]', async () => { + await dataTable.selectItem(file); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version'); + expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?'); + expect(await uploadNewVersionDialog.isDescriptionDisplayed()).toBe(true, 'Description not displayed'); + expect(await uploadNewVersionDialog.isMinorOptionDisplayed()).toBe(true, 'Minor option not displayed'); + expect(await uploadNewVersionDialog.isMajorOptionDisplayed()).toBe(true, 'Major option not displayed'); + expect(await uploadNewVersionDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await uploadNewVersionDialog.isUploadButtonEnabled()).toBe(true, 'Update button not enabled'); + }); + + it('file is updated after uploading a new version - major - [C297552]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload1)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file1Id)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file1Id)).toEqual('1.0', 'File has incorrect version label'); + }); + + it('file is updated after uploading a new version - minor - [C297553]', async () => { + await dataTable.selectItem(file2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new minor version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload2)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file2Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file2Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file is not updated when clicking Cancel - [C297554]', async () => { + await dataTable.selectItem(file3); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload3); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(file3)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file3Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file3Id)).toEqual('', 'File has incorrect version label'); + }); + + it('upload new version fails when new file name already exists - [C297555]', async () => { + await dataTable.selectItem(file4); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(file); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + await page.refresh(); + + expect(await dataTable.isItemPresent(file4)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file4Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file4Id)).toEqual('', 'File has incorrect version label'); + }); + + it('file is unlocked after uploading a new version - [C297556]', async () => { + await dataTable.selectItem(fileLocked1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload4); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload4)).toBe(true, 'File name was not changed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked1Id)).toBe(false, `${fileLocked1} is still locked`); + expect(await apis.user.nodes.getFileVersionType(fileLocked1Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLocked1Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file remains locked after canceling of uploading a new version - [C297557]', async () => { + await dataTable.selectItem(fileLocked2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload5); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(fileToUpload5)).toBe(false, 'File was updated'); + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, 'File not displayed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked2Id)).toBe(true, `${fileLocked2} was unlocked`); + }); + }); + + describe('on Recent Files', () => { + beforeAll(async (done) => { + fileId = (await apis.user.upload.uploadFile(file, parentRFId)).entry.id; + file1Id = (await apis.user.nodes.createFile(file1, parentRFId)).entry.id; + file2Id = (await apis.user.nodes.createFile(file2, parentRFId)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, parentRFId)).entry.id; + file4Id = (await apis.user.nodes.createFile(file4, parentRFId)).entry.id; + + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentRFId)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentRFId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.search.waitForApi(username, { expect: 21 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickRecentFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + // await Utils.pressEscape(); + await page.refresh(); + done(); + }); + + it('dialog UI defaults - [C297558]', async () => { + await dataTable.selectItem(file, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version'); + expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?'); + expect(await uploadNewVersionDialog.isDescriptionDisplayed()).toBe(true, 'Description not displayed'); + expect(await uploadNewVersionDialog.isMinorOptionDisplayed()).toBe(true, 'Minor option not displayed'); + expect(await uploadNewVersionDialog.isMajorOptionDisplayed()).toBe(true, 'Major option not displayed'); + expect(await uploadNewVersionDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await uploadNewVersionDialog.isUploadButtonEnabled()).toBe(true, 'Update button not enabled'); + }); + + it('file is updated after uploading a new version - major - [C297559]', async () => { + await dataTable.selectItem(file1, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload1, parentRF)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file1Id)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file1Id)).toEqual('1.0', 'File has incorrect version label'); + }); + + it('file is updated after uploading a new version - minor - [C297560]', async () => { + await dataTable.selectItem(file2, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new minor version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload2, parentRF)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file2Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file2Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file is not updated when clicking Cancel - [C297561]', async () => { + await dataTable.selectItem(file3, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload3); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(file3, parentRF)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file3Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file3Id)).toEqual('', 'File has incorrect version label'); + }); + + it('upload new version fails when new file name already exists - [C297562]', async () => { + await dataTable.selectItem(file4, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(file); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + await page.refresh(); + + expect(await dataTable.isItemPresent(file4, parentRF)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file4Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file4Id)).toEqual('', 'File has incorrect version label'); + }); + + it('file is unlocked after uploading a new version - [C297563]', async () => { + await dataTable.selectItem(fileLocked1, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload4); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload4, parentRF)).toBe(true, 'File name was not changed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked1Id)).toBe(false, `${fileLocked1} is still locked`); + expect(await apis.user.nodes.getFileVersionType(fileLocked1Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLocked1Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file remains locked after canceling of uploading a new version - [C297564]', async () => { + await dataTable.selectItem(fileLocked2, parentRF); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload5); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(fileToUpload5, parentRF)).toBe(false, 'File was updated'); + expect(await dataTable.isItemPresent(fileLocked2, parentRF)).toBe(true, 'File not displayed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked2Id)).toBe(true, `${fileLocked2} was unlocked`); + }); + }); + + describe('on Favorite Files', () => { + beforeAll(async (done) => { + fileId = (await apis.user.upload.uploadFile(file, parentFavId)).entry.id; + file1Id = (await apis.user.nodes.createFile(file1, parentFavId)).entry.id; + file2Id = (await apis.user.nodes.createFile(file2, parentFavId)).entry.id; + file3Id = (await apis.user.nodes.createFile(file3, parentFavId)).entry.id; + file4Id = (await apis.user.nodes.createFile(file4, parentFavId)).entry.id; + + fileLocked1Id = (await apis.user.nodes.createFile(fileLocked1, parentFavId)).entry.id; + fileLocked2Id = (await apis.user.nodes.createFile(fileLocked2, parentFavId)).entry.id; + + await apis.user.nodes.lockFile(fileLocked1Id); + await apis.user.nodes.lockFile(fileLocked2Id); + + await apis.user.favorites.addFavoritesByIds('file', [fileId, file1Id, file2Id, file3Id, file4Id, fileLocked1Id, fileLocked2Id]); + await apis.user.favorites.waitForApi({ expect: 7 }); + + await loginPage.loginWith(username); + done(); + }); + + beforeEach(async (done) => { + await page.clickFavoritesAndWait(); + done(); + }); + + afterEach(async (done) => { + // await Utils.pressEscape(); + await page.refresh(); + done(); + }); + + it('dialog UI defaults - [C297565]', async () => { + await dataTable.selectItem(file); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version'); + expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?'); + expect(await uploadNewVersionDialog.isDescriptionDisplayed()).toBe(true, 'Description not displayed'); + expect(await uploadNewVersionDialog.isMinorOptionDisplayed()).toBe(true, 'Minor option not displayed'); + expect(await uploadNewVersionDialog.isMajorOptionDisplayed()).toBe(true, 'Major option not displayed'); + expect(await uploadNewVersionDialog.isCancelButtonEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await uploadNewVersionDialog.isUploadButtonEnabled()).toBe(true, 'Update button not enabled'); + }); + + it('file is updated after uploading a new version - major - [C297566]', async () => { + await dataTable.selectItem(file1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload1); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload1)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file1Id)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file1Id)).toEqual('1.0', 'File has incorrect version label'); + }); + + it('file is updated after uploading a new version - minor - [C297567]', async () => { + await dataTable.selectItem(file2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new minor version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload2)).toBe(true, 'File not updated'); + expect(await apis.user.nodes.getFileVersionType(file2Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file2Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file is not updated when clicking Cancel - [C297568]', async () => { + await dataTable.selectItem(file3); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload3); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(file3)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file3Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file3Id)).toEqual('', 'File has incorrect version label'); + }); + + it('upload new version fails when new file name already exists - [C297569]', async () => { + await dataTable.selectItem(file4); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(file); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + await page.refresh(); + + expect(await dataTable.isItemPresent(file4)).toBe(true, 'File was updated'); + expect(await apis.user.nodes.getFileVersionType(file4Id)).toEqual('', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(file4Id)).toEqual('', 'File has incorrect version label'); + }); + + it('file is unlocked after uploading a new version - [C297570]', async () => { + await dataTable.selectItem(fileLocked1); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload4); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await dataTable.isItemPresent(fileToUpload4)).toBe(true, 'File name was not changed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked1Id)).toBe(false, `${fileLocked1} is still locked`); + expect(await apis.user.nodes.getFileVersionType(fileLocked1Id)).toEqual('MINOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLocked1Id)).toEqual('0.1', 'File has incorrect version label'); + }); + + it('file remains locked after canceling of uploading a new version - [C297571]', async () => { + await dataTable.selectItem(fileLocked2); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(fileToUpload5); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMinor(); + await uploadNewVersionDialog.enterDescription('new version description'); + await uploadNewVersionDialog.clickCancel(); + + expect(await dataTable.isItemPresent(fileToUpload5)).toBe(false, 'File was updated'); + expect(await dataTable.isItemPresent(fileLocked2)).toBe(true, 'File not displayed'); + expect(await apis.user.nodes.isFileLockedWrite(fileLocked2Id)).toBe(true, `${fileLocked2} was unlocked`); + }); + }); + +}); diff --git a/e2e/suites/application/general.test.ts b/e2e/suites/application/general.test.ts index f1ffc6c769..393a88aabc 100644 --- a/e2e/suites/application/general.test.ts +++ b/e2e/suites/application/general.test.ts @@ -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,6 @@ describe('General', () => { const { nodes: nodesApi, authentication: authApi } = adminApi; const folder = `folder-${Utils.random()}`; let folderId; - xit(''); describe('on session expire', () => { beforeAll(async (done) => { @@ -61,8 +60,7 @@ describe('General', () => { await createDialog.clickCreate(); - const message = await page.getSnackBarMessage(); - expect(message).toEqual('The action was unsuccessful. Try again or contact your IT Team.'); + expect(await page.getSnackBarMessage()).toEqual('The action was unsuccessful. Try again or contact your IT Team.'); expect(await browser.getTitle()).toContain('Sign in'); diff --git a/e2e/suites/application/page-titles.test.ts b/e2e/suites/application/page-titles.test.ts index cdb636c34a..dbcb51f527 100755 --- a/e2e/suites/application/page-titles.test.ts +++ b/e2e/suites/application/page-titles.test.ts @@ -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 @@ -24,12 +24,11 @@ */ import { browser } from 'protractor'; -import { SIDEBAR_LABELS, PAGE_TITLES } from '../../configs'; +import { PAGE_TITLES } from '../../configs'; import { LoginPage, BrowsingPage } from '../../pages/pages'; import { RepoClient } from '../../utilities/repo-client/repo-client'; import { Utils } from '../../utilities/utils'; - describe('Page titles', () => { const loginPage = new LoginPage(); const page = new BrowsingPage(); @@ -38,8 +37,6 @@ describe('Page titles', () => { const file = `file-${Utils.random()}.txt`; let fileId; const { searchInput } = page.header; - xit(''); - describe('on Login / Logout pages', () => { it('on Login page - [C217155]', async () => { await loginPage.load(); @@ -73,10 +70,8 @@ describe('Page titles', () => { }); it('Personal Files page - [C217157]', async () => { - const label = SIDEBAR_LABELS.PERSONAL_FILES; - - await page.sidenav.navigateToLink(label); - expect(await browser.getTitle()).toContain(label); + await page.clickPersonalFiles(); + expect(await browser.getTitle()).toContain(PAGE_TITLES.PERSONAL_FILES); }); it('My Libraries page - [C217158]', async () => { @@ -90,31 +85,23 @@ describe('Page titles', () => { }); it('Shared Files page - [C217159]', async () => { - const label = SIDEBAR_LABELS.SHARED_FILES; - - await page.sidenav.navigateToLink(label); - expect(await browser.getTitle()).toContain(label); + await page.clickSharedFiles(); + expect(await browser.getTitle()).toContain(PAGE_TITLES.SHARED_FILES); }); it('Recent Files page - [C217160]', async () => { - const label = SIDEBAR_LABELS.RECENT_FILES; - - await page.sidenav.navigateToLink(label); - expect(await browser.getTitle()).toContain(label); + await page.clickRecentFiles(); + expect(await browser.getTitle()).toContain(PAGE_TITLES.RECENT_FILES); }); it('Favorites page - [C217161]', async () => { - const label = SIDEBAR_LABELS.FAVORITES; - - await page.sidenav.navigateToLink(label); - expect(await browser.getTitle()).toContain(label); + await page.clickFavorites(); + expect(await browser.getTitle()).toContain(PAGE_TITLES.FAVORITES); }); it('Trash page - [C217162]', async () => { - const label = SIDEBAR_LABELS.TRASH; - - await page.sidenav.navigateToLink(label); - expect(await browser.getTitle()).toContain(label); + await page.clickTrash(); + expect(await browser.getTitle()).toContain(PAGE_TITLES.TRASH); }); it('File Preview page - [C280415]', async () => { diff --git a/e2e/suites/authentication/login.test.ts b/e2e/suites/authentication/login.test.ts index 85b280eef0..ae7123ebb0 100755 --- a/e2e/suites/authentication/login.test.ts +++ b/e2e/suites/authentication/login.test.ts @@ -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 @@ -34,6 +34,7 @@ import { navigate } from '../../utilities/browser-utils'; describe('Login', () => { const peopleApi = new RepoClient().people; const loginPage = new LoginPage(); + const { login } = loginPage; /* cspell:disable-next-line */ const testUser = `user-${Utils.random()}@alfness`; @@ -73,8 +74,6 @@ describe('Login', () => { done(); }); - xit(''); - describe('general tests', () => { beforeEach(async (done) => { await loginPage.load(); @@ -82,18 +81,18 @@ describe('Login', () => { }); it('login page layout - [C213089]', async () => { - expect(await loginPage.login.usernameInput.isEnabled()).toBe(true, 'username input is not enabled'); - expect(await loginPage.login.passwordInput.isEnabled()).toBe(true, 'password input is not enabled'); - expect(await loginPage.login.submitButton.isEnabled()).toBe(false, 'SIGN IN button is enabled'); - expect(await loginPage.login.getPasswordVisibility()).toBe(false, 'Password is not hidden by default'); + expect(await login.isUsernameEnabled()).toBe(true, 'username input is not enabled'); + expect(await login.isPasswordEnabled()).toBe(true, 'password input is not enabled'); + expect(await login.isSubmitEnabled()).toBe(false, 'SIGN IN button is enabled'); + expect(await login.isPasswordHidden()).toBe(true, 'Password is not hidden by default'); }); it('change password visibility - [C213091]', async () => { - await loginPage.login.enterPassword('some password'); - expect(await loginPage.login.isPasswordShown()).toBe(false, 'password is visible'); - await loginPage.login.passwordVisibility.click(); - expect(await loginPage.login.getPasswordVisibility()).toBe(true, 'Password visibility not changed'); - expect(await loginPage.login.isPasswordShown()).toBe(true, 'password is not visible'); + await login.enterPassword('some password'); + expect(await login.isPasswordDisplayed()).toBe(false, 'password is visible'); + await login.clickPasswordVisibility(); + expect(await login.isPasswordHidden()).toBe(false, 'Password visibility not changed'); + expect(await login.isPasswordDisplayed()).toBe(true, 'password is not visible'); }); }); diff --git a/e2e/suites/authentication/logout.test.ts b/e2e/suites/authentication/logout.test.ts index e0bef04bbf..b6926ea495 100755 --- a/e2e/suites/authentication/logout.test.ts +++ b/e2e/suites/authentication/logout.test.ts @@ -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 @@ -49,7 +49,7 @@ describe('Logout', () => { it('Sign out option is available - [C213143]', async () => { await page.header.userInfo.openMenu(); - expect(await page.header.userInfo.menu.isMenuItemPresent('Sign out')).toBe(true, 'Sign out option not displayed'); + expect(await page.header.isSignOutDisplayed()).toBe(true, 'Sign out option not displayed'); }); it('redirects to Login page on sign out - [C213144]', async () => { diff --git a/e2e/suites/extensions/ext-context-submenus.test.ts b/e2e/suites/extensions/ext-context-submenus.test.ts index 9dc1768be8..e7a38a41e6 100644 --- a/e2e/suites/extensions/ext-context-submenus.test.ts +++ b/e2e/suites/extensions/ext-context-submenus.test.ts @@ -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 diff --git a/e2e/suites/extensions/ext-document-list.test.ts b/e2e/suites/extensions/ext-document-list.test.ts index e0d1d95cd6..554c5c19fe 100644 --- a/e2e/suites/extensions/ext-document-list.test.ts +++ b/e2e/suites/extensions/ext-document-list.test.ts @@ -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 @@ -36,24 +36,24 @@ describe('Extensions - DocumentList presets', () => { const testData = [ { id: 'app.files.name', - fixtureLabel: 'Name' + label: 'Name' }, { id: 'app.files.thumbnail', - fixtureLabel: 'Thumbnail' + label: 'Thumbnail' }, { id: 'app.files.size', - fixtureLabel: 'Size', + label: 'Size', disabled: true }, { id: 'app.files.modifiedBy', - fixtureLabel: 'Test header' + label: 'Test header' }, { id: 'some.id.createdBy', - fixtureLabel: 'New column' + label: 'New column' } ]; @@ -88,20 +88,16 @@ describe('Extensions - DocumentList presets', () => { }); it('Sets the columns to display - [C286700]', async () => { - const labels = testData + const expectedColumns = testData .filter(item => !item.disabled) - .map(data => data.fixtureLabel); - const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label)); + .map(data => data.label); + const actualColumns = await dataTable.getColumnHeadersText(); - expect(await dataTable.getColumnHeaders().count()).toBe(labels.length, 'Incorrect number of columns'); - - await elements.forEach(async (element, index) => { - expect(await element.isPresent()).toBe(true, `"${labels[index]}" is missing`); - }); + expect(actualColumns).toEqual(expectedColumns); }); it('Disabled items are not shown - [C286699]', async () => { - const noColumnLabel = testData.find(item => item.disabled).fixtureLabel; + const noColumnLabel = testData.find(item => item.disabled).label; const element = dataTable.getColumnHeaderByLabel(noColumnLabel); expect(await element.isPresent()).toBe(false, `"${noColumnLabel}" is displayed`); diff --git a/e2e/suites/extensions/ext-header.test.ts b/e2e/suites/extensions/ext-header.test.ts index df26a843fb..8e9b5b76d2 100755 --- a/e2e/suites/extensions/ext-header.test.ts +++ b/e2e/suites/extensions/ext-header.test.ts @@ -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 diff --git a/e2e/suites/extensions/ext-info-drawer.test.ts b/e2e/suites/extensions/ext-info-drawer.test.ts index b8c88a5176..a6a24b7d54 100755 --- a/e2e/suites/extensions/ext-info-drawer.test.ts +++ b/e2e/suites/extensions/ext-info-drawer.test.ts @@ -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 @@ -94,7 +94,7 @@ describe('Extensions - Info Drawer', () => { it('Add a new tab with icon and title - [C284646]', async () => { await page.dataTable.selectItem(file); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); const val = await infoDrawer.getTabTitle(custom_tab.order); @@ -104,7 +104,7 @@ describe('Extensions - Info Drawer', () => { it('Remove existing tab - [C284647]', async () => { await page.dataTable.selectItem(file); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); expect(await infoDrawer.isTabPresent(comments_tab.title)).toBe(false, `${comments_tab.title} tab should not be present!`); @@ -112,7 +112,7 @@ describe('Extensions - Info Drawer', () => { it('Change tab title - [C284648]', async () => { await page.dataTable.selectItem(file); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); expect(await infoDrawer.isTabPresent(properties_tab.title)).toBe(true, `${properties_tab.title} tab is not present`); @@ -121,7 +121,7 @@ describe('Extensions - Info Drawer', () => { it('Tab with icon and no title - [C284649]', async () => { await page.dataTable.selectItem(file); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); expect(await infoDrawer.isTabPresent(no_title_tab.title)).toBe(true, `${no_title_tab.title} tab is not present`); @@ -130,7 +130,7 @@ describe('Extensions - Info Drawer', () => { it('Insert new component in tab - [C284651]', async () => { await page.dataTable.selectItem(file); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); expect(await infoDrawer.isTabDisplayed(custom_tab.title)).toBe(true, `${custom_tab.title} tab is not displayed`); @@ -150,13 +150,11 @@ describe('Extensions - Info Drawer', () => { it('Remove all tabs - [C284650]', async () => { await page.dataTable.selectItem(file); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); expect(await infoDrawer.isEmpty()).toBe(true, 'Info Drawer is not empty'); }); }); - xit(''); - }); diff --git a/e2e/suites/extensions/ext-metadata.test.ts b/e2e/suites/extensions/ext-metadata.test.ts index 7f73656d51..f292b1b43f 100644 --- a/e2e/suites/extensions/ext-metadata.test.ts +++ b/e2e/suites/extensions/ext-metadata.test.ts @@ -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 @@ -83,7 +83,7 @@ describe('Extensions - Metadata presets', () => { await page.refresh(); await page.dataTable.selectItem(file); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); await infoDrawer.clickTab(properties_tab.title); diff --git a/e2e/suites/extensions/ext-viewer.test.ts b/e2e/suites/extensions/ext-viewer.test.ts index d1b66929f4..9acefaca4c 100755 --- a/e2e/suites/extensions/ext-viewer.test.ts +++ b/e2e/suites/extensions/ext-viewer.test.ts @@ -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 @@ -103,8 +103,6 @@ describe('Extensions - Viewer', () => { done(); }); - xit(''); - describe('content', () => { it('Insert new component in a content viewer - [C284659]', async () => { await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); @@ -141,7 +139,7 @@ describe('Extensions - Viewer', () => { await page.dataTable.doubleClickOnRowByName(pdfFile.file_name); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - expect(await toolbar.isButtonPresent('Print')).toBe(false, 'Print button is still displayed'); + expect(await toolbar.isPrintPresent()).toBe(false, 'Print button is still displayed'); }); }); @@ -169,7 +167,7 @@ describe('Extensions - Viewer', () => { expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Permissions')).toBe(false, 'Action is still displayed'); + expect(await toolbar.menu.isManagePermissionsPresent()).toBe(false, 'Action is still displayed'); }); }); }); diff --git a/e2e/suites/info-drawer/comments.test.ts b/e2e/suites/info-drawer/comments.test.ts new file mode 100755 index 0000000000..d2f0ced841 --- /dev/null +++ b/e2e/suites/info-drawer/comments.test.ts @@ -0,0 +1,398 @@ +/*! + * @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 . + */ + +import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { RepoClient } from '../../utilities/repo-client/repo-client'; +import { InfoDrawer } from './../../components/info-drawer/info-drawer'; +import { Utils } from '../../utilities/utils'; +import * as moment from 'moment'; + +describe('Comments', () => { + const username = `user1-${Utils.random()}`; + + const parent = `parent-${Utils.random()}`; let parentId; + + const file1 = `file1-${Utils.random()}.txt`; + + const fileWith1Comment = `file1Comment-${Utils.random()}.txt`; let fileWith1CommentId; + const fileWith2Comments = `file2Comments-${Utils.random()}.txt`; let fileWith2CommentsId; + + const file2Personal = `file2Personal-${Utils.random()}.txt`; + const file2Shared = `file2Shared-${Utils.random()}.txt`; let file2SharedId; + const file2Recent = `file2Recent-${Utils.random()}.txt`; + const file2Favorites = `file2Favorites-${Utils.random()}.txt`; let file2FavoritesId; + + let commentFile1Entry; + let comment1File2Entry, comment2File2Entry; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const infoDrawer = new InfoDrawer(); + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable } = page; + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + + await apis.user.nodes.createFile(file1, parentId); + await apis.user.nodes.createFile(file2Personal, parentId); + await apis.user.nodes.createFile(file2Recent, parentId); + file2SharedId = (await apis.user.nodes.createFile(file2Shared, parentId)).entry.id + file2FavoritesId = (await apis.user.nodes.createFile(file2Favorites, parentId)).entry.id; + + fileWith1CommentId = (await apis.user.nodes.createFile(fileWith1Comment, parentId)).entry.id; + fileWith2CommentsId = (await apis.user.nodes.createFile(fileWith2Comments, parentId)).entry.id; + + commentFile1Entry = (await apis.user.comments.addComment(fileWith1CommentId, 'this is my comment')).entry; + + comment1File2Entry = (await apis.user.comments.addComment(fileWith2CommentsId, 'first comment')).entry; + comment2File2Entry = (await apis.user.comments.addComment(fileWith2CommentsId, 'second comment')).entry; + + await apis.user.shared.shareFilesByIds([file2SharedId, fileWith1CommentId, fileWith2CommentsId]); + await apis.user.favorites.addFavoritesByIds('file', [file2FavoritesId, fileWith1CommentId, fileWith2CommentsId]); + + await loginPage.loginWith(username); + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentId); + done(); + }); + + describe('from Personal Files', () => { + beforeEach(async (done) => { + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parent); + done(); + }); + + afterEach(async (done) => { + await dataTable.clearSelection(); + done(); + }); + + it('Comments tab default fields - [C299173]', async () => { + await dataTable.selectItem(file1); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getActiveTabTitle()).toBe('COMMENTS'); + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (0)'); + expect(await infoDrawer.isCommentTextAreaDisplayed()).toBe(true, 'Comment field not present'); + expect(await infoDrawer.isAddCommentButtonEnabled()).toBe(false, 'Add comment button not disabled'); + }); + + it('Comment info display - [C280582]', async () => { + await dataTable.selectItem(fileWith1Comment); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (1)'); + expect(await infoDrawer.isCommentTextAreaDisplayed()).toBe(true, 'Comment field not present'); + expect(await infoDrawer.isAddCommentButtonEnabled()).toBe(false, 'Add comment button not disabled'); + + expect(await infoDrawer.isCommentDisplayed(commentFile1Entry.id)).toBe(true, `Comment with id: ${commentFile1Entry.id} not displayed`); + expect(await infoDrawer.getCommentText(commentFile1Entry.id)).toBe(commentFile1Entry.content, 'Incorrect comment text'); + expect(await infoDrawer.getCommentUserName(commentFile1Entry.id)).toBe(`${username} ${username}`, 'Incorrect comment user'); + expect(await infoDrawer.getCommentTime(commentFile1Entry.id)).toBe(moment(commentFile1Entry.createdAt).fromNow(), 'Incorrect comment created time'); + expect(await infoDrawer.isCommentUserAvatarDisplayed(commentFile1Entry.id)).toBe(true, 'User avatar not displayed'); + }); + + it('Comments are displayed ordered by created date in descending order - [C280583]', async () => { + await dataTable.selectItem(fileWith2Comments); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getNthCommentId(1)).toContain(comment2File2Entry.id); + expect(await infoDrawer.getNthCommentId(2)).toContain(comment1File2Entry.id); + }); + + it('Total number of comments is displayed - [C280585]', async () => { + await dataTable.selectItem(fileWith2Comments); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (2)'); + }); + + it('Add button is enabled when typing in the comment field - [C280589]', async () => { + await dataTable.selectItem(file1); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.isAddCommentButtonEnabled()).toBe(false, 'Add comment button not disabled'); + + await infoDrawer.typeComment('my comment'); + expect(await infoDrawer.isAddCommentButtonEnabled()).toBe(true, 'Add comment button not enabled'); + }); + + it('Add a comment - [C280590]', async () => { + const myComment = 'my comment'; + + await dataTable.selectItem(file2Personal); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + await infoDrawer.typeComment(myComment); + await infoDrawer.clickAddButton(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (1)'); + expect(await infoDrawer.isCommentDisplayed()).toBe(true, `Comment not displayed`); + expect(await infoDrawer.getCommentText()).toBe(myComment, 'Incorrect comment text'); + }); + + it('Escape key clears the text when focus is on the textarea - [C280591]', async () => { + await dataTable.selectItem(file2Personal); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + await infoDrawer.typeComment('myComment'); + + expect(await infoDrawer.getCommentTextFromTextArea()).toBe('myComment'); + + await Utils.pressEscape(); + + expect(await infoDrawer.getCommentTextFromTextArea()).toBe(''); + }); + }); + + describe('from Favorites', () => { + beforeAll(async (done) => { + await apis.user.favorites.waitForApi({ expect: 3 }); + done(); + }); + + beforeEach(async (done) => { + await page.clickFavoritesAndWait(); + done(); + }); + + afterEach(async (done) => { + await dataTable.clearSelection(); + done(); + }); + + it('Comment info display - [C299196]', async () => { + await dataTable.selectItem(fileWith1Comment); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (1)'); + expect(await infoDrawer.isCommentTextAreaDisplayed()).toBe(true, 'Comment field not present'); + expect(await infoDrawer.isAddCommentButtonEnabled()).toBe(false, 'Add comment button not disabled'); + + expect(await infoDrawer.isCommentDisplayed(commentFile1Entry.id)).toBe(true, `Comment with id: ${commentFile1Entry.id} not displayed`); + expect(await infoDrawer.getCommentText(commentFile1Entry.id)).toBe(commentFile1Entry.content, 'Incorrect comment text'); + expect(await infoDrawer.getCommentUserName(commentFile1Entry.id)).toBe(`${username} ${username}`, 'Incorrect comment user'); + expect(await infoDrawer.getCommentTime(commentFile1Entry.id)).toBe(moment(commentFile1Entry.createdAt).fromNow(), 'Incorrect comment created time'); + expect(await infoDrawer.isCommentUserAvatarDisplayed(commentFile1Entry.id)).toBe(true, 'User avatar not displayed'); + }); + + it('Comments are displayed ordered by created date in descending order - [C299197]', async () => { + await dataTable.selectItem(fileWith2Comments); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getNthCommentId(1)).toContain(comment2File2Entry.id); + expect(await infoDrawer.getNthCommentId(2)).toContain(comment1File2Entry.id); + }); + + it('Total number of comments is displayed - [C299198]', async () => { + await dataTable.selectItem(fileWith2Comments); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (2)'); + }); + + it('Add a comment - [C299199]', async () => { + const myComment = 'my comment'; + + await dataTable.selectItem(file2Favorites); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + await infoDrawer.typeComment(myComment); + await infoDrawer.clickAddButton(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (1)'); + expect(await infoDrawer.isCommentDisplayed()).toBe(true, `Comment not displayed`); + expect(await infoDrawer.getCommentText()).toBe(myComment, 'Incorrect comment text'); + }); + }); + + describe('from Shared Files', () => { + beforeAll(async (done) => { + await apis.user.shared.waitForApi({ expect: 3 }); + done(); + }); + + beforeEach(async (done) => { + await page.clickSharedFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + await dataTable.clearSelection(); + done(); + }); + + it('Comment info display - [C299188]', async () => { + await dataTable.selectItem(fileWith1Comment); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (1)'); + expect(await infoDrawer.isCommentTextAreaDisplayed()).toBe(true, 'Comment field not present'); + expect(await infoDrawer.isAddCommentButtonEnabled()).toBe(false, 'Add comment button not disabled'); + + expect(await infoDrawer.isCommentDisplayed(commentFile1Entry.id)).toBe(true, `Comment with id: ${commentFile1Entry.id} not displayed`); + expect(await infoDrawer.getCommentText(commentFile1Entry.id)).toBe(commentFile1Entry.content, 'Incorrect comment text'); + expect(await infoDrawer.getCommentUserName(commentFile1Entry.id)).toBe(`${username} ${username}`, 'Incorrect comment user'); + expect(await infoDrawer.getCommentTime(commentFile1Entry.id)).toBe(moment(commentFile1Entry.createdAt).fromNow(), 'Incorrect comment created time'); + expect(await infoDrawer.isCommentUserAvatarDisplayed(commentFile1Entry.id)).toBe(true, 'User avatar not displayed'); + }); + + it('Comments are displayed ordered by created date in descending order - [C299189]', async () => { + await dataTable.selectItem(fileWith2Comments); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getNthCommentId(1)).toContain(comment2File2Entry.id); + expect(await infoDrawer.getNthCommentId(2)).toContain(comment1File2Entry.id); + }); + + it('Total number of comments is displayed - [C299190]', async () => { + await dataTable.selectItem(fileWith2Comments); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (2)'); + }); + + it('Add a comment - [C299191]', async () => { + const myComment = 'my comment'; + + await dataTable.selectItem(file2Shared); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + await infoDrawer.typeComment(myComment); + await infoDrawer.clickAddButton(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (1)'); + expect(await infoDrawer.isCommentDisplayed()).toBe(true, `Comment not displayed`); + expect(await infoDrawer.getCommentText()).toBe(myComment, 'Incorrect comment text'); + }); + }); + + describe('from Recent Files', () => { + beforeAll(async (done) => { + await apis.user.search.waitForApi(username, { expect: 7 }); + done(); + }); + + beforeEach(async (done) => { + await page.clickRecentFilesAndWait(); + done(); + }); + + afterEach(async (done) => { + await dataTable.clearSelection(); + done(); + }); + + it('Comment info display - [C299192]', async () => { + await dataTable.selectItem(fileWith1Comment); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (1)'); + expect(await infoDrawer.isCommentTextAreaDisplayed()).toBe(true, 'Comment field not present'); + expect(await infoDrawer.isAddCommentButtonEnabled()).toBe(false, 'Add comment button not disabled'); + + expect(await infoDrawer.isCommentDisplayed(commentFile1Entry.id)).toBe(true, `Comment with id: ${commentFile1Entry.id} not displayed`); + expect(await infoDrawer.getCommentText(commentFile1Entry.id)).toBe(commentFile1Entry.content, 'Incorrect comment text'); + expect(await infoDrawer.getCommentUserName(commentFile1Entry.id)).toBe(`${username} ${username}`, 'Incorrect comment user'); + expect(await infoDrawer.getCommentTime(commentFile1Entry.id)).toBe(moment(commentFile1Entry.createdAt).fromNow(), 'Incorrect comment created time'); + expect(await infoDrawer.isCommentUserAvatarDisplayed(commentFile1Entry.id)).toBe(true, 'User avatar not displayed'); + }); + + it('Comments are displayed ordered by created date in descending order - [C299193]', async () => { + await dataTable.selectItem(fileWith2Comments); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getNthCommentId(1)).toContain(comment2File2Entry.id); + expect(await infoDrawer.getNthCommentId(2)).toContain(comment1File2Entry.id); + }); + + it('Total number of comments is displayed - [C299194]', async () => { + await dataTable.selectItem(fileWith2Comments); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (2)'); + }); + + it('Add a comment - [C299195]', async () => { + const myComment = 'my comment'; + + await dataTable.selectItem(file2Recent); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + await infoDrawer.clickCommentsTab(); + await infoDrawer.typeComment(myComment); + await infoDrawer.clickAddButton(); + + expect(await infoDrawer.getCommentsTabHeaderText()).toBe('Comments (1)'); + expect(await infoDrawer.isCommentDisplayed()).toBe(true, `Comment not displayed`); + expect(await infoDrawer.getCommentText()).toBe(myComment, 'Incorrect comment text'); + }); + }); + +}); diff --git a/e2e/suites/info-drawer/general.test.ts b/e2e/suites/info-drawer/general.test.ts new file mode 100755 index 0000000000..4add293f9b --- /dev/null +++ b/e2e/suites/info-drawer/general.test.ts @@ -0,0 +1,90 @@ +/*! + * @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 . + */ + +import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { RepoClient } from '../../utilities/repo-client/repo-client'; +import { InfoDrawer } from './../../components/info-drawer/info-drawer'; +import { Utils } from '../../utilities/utils'; + +describe('General', () => { + const username = `user1-${Utils.random()}`; + + const parent = `parent-${Utils.random()}`; let parentId; + + const file1 = `file1-${Utils.random()}.txt`; + const folder1 = `folder1-${Utils.random()}`; + + const apis = { + admin: new RepoClient(), + user: new RepoClient(username, username) + }; + + const infoDrawer = new InfoDrawer(); + + const loginPage = new LoginPage(); + const page = new BrowsingPage(); + const { dataTable } = page; + + beforeAll(async (done) => { + await apis.admin.people.createUser({ username }); + + parentId = (await apis.user.nodes.createFolder(parent)).entry.id; + await apis.user.nodes.createFile(file1, parentId); + await apis.user.nodes.createFolder(folder1, parentId); + + await loginPage.loginWith(username); + done(); + }); + + afterAll(async (done) => { + await apis.user.nodes.deleteNodeById(parentId); + done(); + }); + + beforeEach(async (done) => { + await page.clickPersonalFilesAndWait(); + await dataTable.doubleClickOnRowByName(parent); + done(); + }); + + afterEach(async (done) => { + if (await infoDrawer.isOpen()) { + await page.toolbar.clickViewDetails(); + } + done(); + }); + + it('Info drawer for a file - default tabs - [C299162]', async () => { + await dataTable.selectItem(file1); + await page.toolbar.clickViewDetails(); + await infoDrawer.waitForInfoDrawerToOpen(); + + expect(await infoDrawer.getHeaderTitle()).toEqual('Details'); + expect(await infoDrawer.isPropertiesTabDisplayed()).toBe(true, 'Properties tab is not displayed'); + expect(await infoDrawer.isCommentsTabDisplayed()).toBe(true, 'Comments tab is not displayed'); + expect(await infoDrawer.getTabsCount()).toBe(2, 'Incorrect number of tabs'); + }); + +}); diff --git a/e2e/suites/info-drawer/library-properties.test.ts b/e2e/suites/info-drawer/library-properties.test.ts index 63a7de6f3d..032db8baaa 100755 --- a/e2e/suites/info-drawer/library-properties.test.ts +++ b/e2e/suites/info-drawer/library-properties.test.ts @@ -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 @@ -96,18 +96,18 @@ describe('Library properties', () => { afterEach(async done => { if (await infoDrawer.isOpen()) { - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); } done(); }); it('Info drawer opens for a library - [C289336]', async () => { await dataTable.selectItem(site.name); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); expect(await infoDrawer.getHeaderTitle()).toEqual('Details'); - expect(await infoDrawer.isTabPresent('About')).toBe(true, 'About tab is not displayed'); + expect(await infoDrawer.isAboutTabDisplayed()).toBe(true, 'About tab is not displayed'); expect(await infoDrawer.isNameDisplayed()).toBe(true, 'Name field not displayed'); expect(await infoDrawer.isLibraryIdDisplayed()).toBe(true, 'Library ID field not displayed'); expect(await infoDrawer.isVisibilityDisplayed()).toBe(true, 'Visibility field not displayed'); @@ -118,45 +118,45 @@ describe('Library properties', () => { expect((await infoDrawer.getVisibility()).toLowerCase()).toEqual((site.visibility).toLowerCase()); expect(await infoDrawer.getDescription()).toEqual(site.description); - expect(await infoDrawer.isButtonDisplayed('Edit')).toBe(true, 'Edit action is not displayed'); + expect(await infoDrawer.isEditDisplayed()).toBe(true, 'Edit action is not displayed'); }); it('Editable properties - [C289338]', async () => { await dataTable.selectItem(site.name); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); - expect(await infoDrawer.isButtonEnabled('Edit')).toBe(true, 'Edit action is not enabled'); - await infoDrawer.clickButton('Edit'); + expect(await infoDrawer.isEditEnabled()).toBe(true, 'Edit action is not enabled'); + await infoDrawer.clickEdit(); expect(await infoDrawer.isNameEnabled()).toBe(true, 'Name field not enabled'); expect(await infoDrawer.isLibraryIdEnabled()).toBe(false, 'Library ID field not disabled'); expect(await infoDrawer.isVisibilityEnabled()).toBe(true, 'Visibility field not enabled'); expect(await infoDrawer.isDescriptionEnabled()).toBe(true, 'Description field not enabled'); - expect(await infoDrawer.isButtonDisplayed('Cancel')).toBe(true, 'Cancel button not displayed'); - expect(await infoDrawer.isButtonDisplayed('Update')).toBe(true, 'Update button not displayed'); - expect(await infoDrawer.isButtonEnabled('Cancel')).toBe(true, 'Cancel button not enabled'); - expect(await infoDrawer.isButtonEnabled('Update')).toBe(false, 'Update button not disabled'); + expect(await infoDrawer.isCancelDisplayed()).toBe(true, 'Cancel button not displayed'); + expect(await infoDrawer.isUpdateDisplayed()).toBe(true, 'Update button not displayed'); + expect(await infoDrawer.isCancelEnabled()).toBe(true, 'Cancel button not enabled'); + expect(await infoDrawer.isUpdateEnabled()).toBe(false, 'Update button not disabled'); }); it('Edit site details - [C289339]', async () => { await dataTable.selectItem(siteForUpdate.name); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); - expect(await infoDrawer.isButtonEnabled('Edit')).toBe(true, 'Edit action is not enabled'); - await infoDrawer.clickButton('Edit'); + expect(await infoDrawer.isEditEnabled()).toBe(true, 'Edit action is not enabled'); + await infoDrawer.clickEdit(); await infoDrawer.enterName(siteUpdated.name); await infoDrawer.enterDescription(siteUpdated.description); await infoDrawer.setVisibility(siteUpdated.visibility); - expect(await infoDrawer.isButtonEnabled('Update')).toBe(true, 'Update button not enabled'); + expect(await infoDrawer.isUpdateEnabled()).toBe(true, 'Update button not enabled'); - await infoDrawer.clickButton('Update'); + await infoDrawer.clickUpdate(); expect(await page.getSnackBarMessage()).toEqual('Library properties updated'); - expect(await dataTable.getRowByName(siteUpdated.name).isPresent()).toBe(true, 'New site name not displayed in the list'); + expect(await dataTable.isItemPresent(siteUpdated.name)).toBe(true, 'New site name not displayed in the list'); expect(await infoDrawer.isOpen()).toBe(false, 'Info drawer still open'); expect((await apis.user.sites.getSite(siteForUpdate.id)).entry.title).toEqual(siteUpdated.name); @@ -169,30 +169,30 @@ describe('Library properties', () => { const newDesc = `new desc ${Utils.random}`; await dataTable.selectItem(site.name); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); - expect(await infoDrawer.isButtonEnabled('Edit')).toBe(true, 'Edit action is not enabled'); - await infoDrawer.clickButton('Edit'); + expect(await infoDrawer.isEditEnabled()).toBe(true, 'Edit action is not enabled'); + await infoDrawer.clickEdit(); await infoDrawer.enterName(newName); await infoDrawer.enterDescription(newDesc); await infoDrawer.setVisibility(SITE_VISIBILITY.MODERATED); - await infoDrawer.clickButton('Cancel'); + await infoDrawer.clickCancel(); - expect(await dataTable.getRowByName(newName).isPresent()).toBe(false, 'New site name is displayed in the list'); - expect(await dataTable.getRowByName(site.name).isPresent()).toBe(true, 'Original site name not displayed in the list'); + expect(await dataTable.isItemPresent(newName)).toBe(false, 'New site name is displayed in the list'); + expect(await dataTable.isItemPresent(site.name)).toBe(true, 'Original site name not displayed in the list'); expect(await infoDrawer.isOpen()).toBe(true, 'Info drawer not open'); }); it('Warning appears when editing the name of the library by entering an existing name - [C289341]', async () => { - await apis.user.queries.waitForApi(site.name, { expect: 1 }); + await apis.user.queries.waitForSites(site.name, { expect: 1 }); await dataTable.selectItem(siteDup); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); - await infoDrawer.clickButton('Edit'); + await infoDrawer.clickEdit(); await infoDrawer.enterName(site.name); expect(await infoDrawer.isMessageDisplayed()).toBe(true, 'Message not displayed'); @@ -201,28 +201,28 @@ describe('Library properties', () => { it('Site name too long - [C289342]', async () => { await dataTable.selectItem(site.name); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); - await infoDrawer.clickButton('Edit'); + await infoDrawer.clickEdit(); await infoDrawer.enterName(Utils.string257); await Utils.pressTab(); expect(await infoDrawer.isErrorDisplayed()).toBe(true, 'Message not displayed'); expect(await infoDrawer.getError()).toEqual('Use 256 characters or less for title'); - expect(await infoDrawer.isButtonEnabled('Update')).toBe(false, 'Update button not disabled'); + expect(await infoDrawer.isUpdateEnabled()).toBe(false, 'Update button not disabled'); }); it('Site description too long - [C289343]', async () => { await dataTable.selectItem(site.name); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); - await infoDrawer.clickButton('Edit'); + await infoDrawer.clickEdit(); await infoDrawer.enterDescription(Utils.string513); await Utils.pressTab(); expect(await infoDrawer.isErrorDisplayed()).toBe(true, 'Message not displayed'); expect(await infoDrawer.getError()).toEqual('Use 512 characters or less for description'); - expect(await infoDrawer.isButtonEnabled('Update')).toBe(false, 'Update button not disabled'); + expect(await infoDrawer.isUpdateEnabled()).toBe(false, 'Update button not disabled'); }); describe('Non manager', () => { @@ -236,9 +236,9 @@ describe('Library properties', () => { await page.clickFileLibrariesAndWait(); await dataTable.selectItem(site.name); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); - expect(await infoDrawer.isButtonDisplayed('Edit')).toBe(false, 'Edit action is displayed'); + expect(await infoDrawer.isEditDisplayed()).toBe(false, 'Edit action is displayed'); }); it('Error notification - [C289344]', async () => { @@ -246,14 +246,14 @@ describe('Library properties', () => { await page.clickFileLibrariesAndWait(); await dataTable.selectItem(site.name); - await page.toolbar.getButtonByTitleAttribute('View details').click(); + await page.toolbar.clickViewDetails(); await infoDrawer.waitForInfoDrawerToOpen(); - await infoDrawer.clickButton('Edit'); + await infoDrawer.clickEdit(); await apis.user.sites.updateSiteMember(site.id, user3, SITE_ROLES.SITE_CONSUMER.ROLE); await infoDrawer.enterDescription('new description'); - await infoDrawer.clickButton('Update'); + await infoDrawer.clickUpdate(); expect(await page.getSnackBarMessage()).toEqual('There was an error updating library properties'); }); diff --git a/e2e/suites/list-views/empty-list.test.ts b/e2e/suites/list-views/empty-list.test.ts index 879f12a497..b8fa7e43ea 100755 --- a/e2e/suites/list-views/empty-list.test.ts +++ b/e2e/suites/list-views/empty-list.test.ts @@ -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 @@ -98,62 +98,72 @@ describe('Empty list views', () => { it('Favorites - pagination controls not displayed - [C280111]', async () => { await page.clickFavorites(); - expect(await pagination.range.isPresent()).toBe(false); - expect(await pagination.maxItems.isPresent()).toBe(false); - expect(await pagination.currentPage.isPresent()).toBe(false); - expect(await pagination.totalPages.isPresent()).toBe(false); - expect(await pagination.previousButton.isPresent()).toBe(false); - expect(await pagination.nextButton.isPresent()).toBe(false); + expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); + expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); + expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); + expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); + expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); + expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); }); - it('File Libraries - pagination controls not displayed - [C280084]', async () => { - await page.clickFileLibraries(); - expect(await pagination.range.isPresent()).toBe(false); - expect(await pagination.maxItems.isPresent()).toBe(false); - expect(await pagination.currentPage.isPresent()).toBe(false); - expect(await pagination.totalPages.isPresent()).toBe(false); - expect(await pagination.previousButton.isPresent()).toBe(false); - expect(await pagination.nextButton.isPresent()).toBe(false); + it('My Libraries - pagination controls not displayed - [C280084]', async () => { + await page.goToMyLibraries(); + expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); + expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); + expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); + expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); + expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); + expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); + }); + + it('Favorite Libraries - pagination controls not displayed - [C291873]', async () => { + await page.goToFavoriteLibraries(); + expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); + expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); + expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); + expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); + expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); + expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); }); it('Personal Files - pagination controls not displayed - [C280075]', async () => { await page.clickPersonalFiles(); - expect(await pagination.range.isPresent()).toBe(false); - expect(await pagination.maxItems.isPresent()).toBe(false); - expect(await pagination.currentPage.isPresent()).toBe(false); - expect(await pagination.totalPages.isPresent()).toBe(false); - expect(await pagination.previousButton.isPresent()).toBe(false); - expect(await pagination.nextButton.isPresent()).toBe(false); + expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); + expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); + expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); + expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); + expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); + expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); }); it('Recent Files - pagination controls not displayed - [C280102]', async () => { await page.clickRecentFiles(); - expect(await pagination.range.isPresent()).toBe(false); - expect(await pagination.maxItems.isPresent()).toBe(false); - expect(await pagination.currentPage.isPresent()).toBe(false); - expect(await pagination.totalPages.isPresent()).toBe(false); - expect(await pagination.previousButton.isPresent()).toBe(false); - expect(await pagination.nextButton.isPresent()).toBe(false); + expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); + expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); + expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); + expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); + expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); + expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); }); it('Shared Files - pagination controls not displayed - [C280094]', async () => { await page.clickSharedFiles(); - expect(await pagination.range.isPresent()).toBe(false); - expect(await pagination.maxItems.isPresent()).toBe(false); - expect(await pagination.currentPage.isPresent()).toBe(false); - expect(await pagination.totalPages.isPresent()).toBe(false); - expect(await pagination.previousButton.isPresent()).toBe(false); - expect(await pagination.nextButton.isPresent()).toBe(false); + expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); + expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); + expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); + expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); + expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); + expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); }); it('Trash - pagination controls not displayed - [C280120]', async () => { await page.clickTrash(); - expect(await pagination.range.isPresent()).toBe(false); - expect(await pagination.maxItems.isPresent()).toBe(false); - expect(await pagination.currentPage.isPresent()).toBe(false); - expect(await pagination.totalPages.isPresent()).toBe(false); - expect(await pagination.previousButton.isPresent()).toBe(false); - expect(await pagination.nextButton.isPresent()).toBe(false); + expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); + expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); + expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); + expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); + expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); + expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); }); it('Search results - pagination controls not displayed - [C290123]', async () => { @@ -163,11 +173,11 @@ describe('Empty list views', () => { await searchInput.searchFor('qwertyuiop'); await dataTable.waitForBody(); - expect(await pagination.range.isPresent()).toBe(false); - expect(await pagination.maxItems.isPresent()).toBe(false); - expect(await pagination.currentPage.isPresent()).toBe(false); - expect(await pagination.totalPages.isPresent()).toBe(false); - expect(await pagination.previousButton.isPresent()).toBe(false); - expect(await pagination.nextButton.isPresent()).toBe(false); + expect(await pagination.isRangePresent()).toBe(false, 'Range is present'); + expect(await pagination.isMaxItemsPresent()).toBe(false, 'Max items is present'); + expect(await pagination.isCurrentPagePresent()).toBe(false, 'Current page is present'); + expect(await pagination.isTotalPagesPresent()).toBe(false, 'Total pages is present'); + expect(await pagination.isPreviousButtonPresent()).toBe(false, 'Previous button is present'); + expect(await pagination.isNextButtonPresent()).toBe(false, 'Next button is present'); }); }); diff --git a/e2e/suites/list-views/favorites.test.ts b/e2e/suites/list-views/favorites.test.ts index d210203e32..dbef1d15e0 100755 --- a/e2e/suites/list-views/favorites.test.ts +++ b/e2e/suites/list-views/favorites.test.ts @@ -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 @@ -88,27 +88,25 @@ describe('Favorites', () => { }); it('has the correct columns - [C280482]', async () => { - const expectedHeader = [ 'Thumbnail', 'Name', 'Location', 'Size', 'Modified', 'Modified by' ]; - const headers = dataTable.getColumnHeaders(); - const count = await headers.count(); - expect(count).toBe(5 + 1, 'Incorrect number of columns'); + const expectedColumns = [ 'Thumbnail', 'Name', 'Location', 'Size', 'Modified', 'Modified by' ]; + const actualColumns = await dataTable.getColumnHeadersText(); - expect(await dataTable.getHeaderText()).toEqual(expectedHeader); + expect(actualColumns).toEqual(expectedColumns); }); it('displays the favorite files and folders - [C213226]', async () => { expect(await dataTable.countRows()).toEqual(4, 'Incorrect number of items displayed'); - expect(await dataTable.getRowByName(fileName1).isPresent()).toBe(true, `${fileName1} not displayed`); - expect(await dataTable.getRowByName(fileName2).isPresent()).toBe(true, `${fileName2} not displayed`); - expect(await dataTable.getRowByName(favFolderName).isPresent()).toBe(true, `${favFolderName} not displayed`); + expect(await dataTable.isItemPresent(fileName1)).toBe(true, `${fileName1} not displayed`); + expect(await dataTable.isItemPresent(fileName2)).toBe(true, `${fileName2} not displayed`); + expect(await dataTable.isItemPresent(favFolderName)).toBe(true, `${favFolderName} not displayed`); }); it(`deleted favorite file does not appear - [C213228]`, async () => { - expect(await dataTable.getRowByName(fileName3).isPresent()).not.toBe(true, `${fileName3} is displayed`); + expect(await dataTable.isItemPresent(fileName3)).not.toBe(true, `${fileName3} is displayed`); }); it(`file is displayed after it is restored from Trashcan - [C213229]`, async () => { - expect(await dataTable.getRowByName(fileName4).isPresent()).toBe(true, `${fileName4} not displayed`); + expect(await dataTable.isItemPresent(fileName4)).toBe(true, `${fileName4} not displayed`); }); it('Location column displays the parent folder of the files - [C213231]', async () => { @@ -118,9 +116,9 @@ describe('Favorites', () => { }); it('Location column displays a tooltip with the entire path of the file - [C213671]', async () => { - expect(await dataTable.getItemLocationTileAttr(fileName1)).toEqual(`File Libraries/${siteName}`); - expect(await dataTable.getItemLocationTileAttr(fileName2)).toEqual(`Personal Files/${parentFolder}`); - expect(await dataTable.getItemLocationTileAttr(favFolderName)).toEqual('Personal Files'); + expect(await dataTable.getItemLocationTooltip(fileName1)).toEqual(`File Libraries/${siteName}`); + expect(await dataTable.getItemLocationTooltip(fileName2)).toEqual(`Personal Files/${parentFolder}`); + expect(await dataTable.getItemLocationTooltip(favFolderName)).toEqual('Personal Files'); }); it('Location column redirect - item in user Home - [C213650]', async () => { diff --git a/e2e/suites/list-views/file-libraries.test.ts b/e2e/suites/list-views/file-libraries.test.ts index 5de73cc6e4..7ff6e3847a 100755 --- a/e2e/suites/list-views/file-libraries.test.ts +++ b/e2e/suites/list-views/file-libraries.test.ts @@ -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 @@ -96,30 +96,24 @@ describe('File Libraries', () => { done(); }); - xit(''); - describe('My Libraries', () => { beforeEach(async (done) => { - await page.goToMyLibraries(); + await page.goToMyLibrariesAndWait(); done(); }); it('has the correct columns - [C217095]', async () => { - const labels = [ 'Name', 'My Role', 'Visibility' ]; - const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label)); - - expect(await dataTable.getColumnHeaders().count()).toBe(3 + 1, 'Incorrect number of columns'); + const expectedColumns = [ 'Thumbnail', 'Name', 'My Role', 'Visibility' ]; + const actualColumns = await dataTable.getColumnHeadersText(); - await elements.forEach(async (element, index) => { - expect(await element.isPresent()).toBe(true, `"${labels[index]}" is missing`); - }); + expect(actualColumns).toEqual(expectedColumns); }); it('User can see only the sites he is a member of - [C280501]', async () => { const sitesCount = await dataTable.countRows(); expect(sitesCount).toEqual(10, 'Incorrect number of sites displayed'); - expect(await dataTable.getRowByName(adminSite5).isPresent()).toBe(false, `${adminSite5} should not appear in the list`); + expect(await dataTable.isItemPresent(adminSite5)).toBe(false, `${adminSite5} should not appear in the list`); }); it('Library visibility is correctly displayed - [C289905]', async () => { @@ -129,17 +123,11 @@ describe('File Libraries', () => { [userSitePublic]: SITE_VISIBILITY.PUBLIC }; - const rowCells = await dataTable.getRows().map((row) => { - return row.all(dataTable.cell).map(async cell => await cell.getText()); - }); - const sitesList = rowCells.reduce((acc, cell) => { - acc[cell[1]] = cell[3].toUpperCase(); - return acc; - }, {}); + const sitesList = await dataTable.getSitesNameAndVisibility(); - Object.keys(expectedSitesVisibility).forEach((site) => { + for (const site of Object.keys(expectedSitesVisibility)) { expect(sitesList[site]).toEqual(expectedSitesVisibility[site]); - }); + } }); it('User role is correctly displayed - [C289903]', async () => { @@ -150,17 +138,11 @@ describe('File Libraries', () => { [adminSite4]: SITE_ROLES.SITE_MANAGER.LABEL }; - const rowCells = await dataTable.getRows().map((row) => { - return row.all(dataTable.cell).map(async cell => await cell.getText()); - }); - const sitesList = rowCells.reduce((acc, cell) => { - acc[cell[1]] = cell[2]; - return acc; - }, {}); + const sitesList = await dataTable.getSitesNameAndRole(); - Object.keys(expectedSitesRoles).forEach((site) => { + for (const site of Object.keys(expectedSitesRoles)) { expect(sitesList[site]).toEqual(expectedSitesRoles[site]); - }); + } }); it('Site ID is displayed when two sites have the same name - [C217098]', async () => { @@ -187,26 +169,22 @@ describe('File Libraries', () => { describe('Favorite Libraries', () => { beforeEach(async (done) => { - await page.goToFavoriteLibraries(); + await page.goToFavoriteLibrariesAndWait(); done(); }); it('has the correct columns - [C289893]', async () => { - const labels = [ 'Name', 'My Role', 'Visibility' ]; - const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label)); - - expect(await dataTable.getColumnHeaders().count()).toBe(3 + 1, 'Incorrect number of columns'); + const expectedColumns = [ 'Thumbnail', 'Name', 'My Role', 'Visibility' ]; + const actualColumns = await dataTable.getColumnHeadersText(); - await elements.forEach(async (element, index) => { - expect(await element.isPresent()).toBe(true, `"${labels[index]}" is missing`); - }); + expect(actualColumns).toEqual(expectedColumns); }); it('User can see only his favorite sites - [C289897]', async () => { const sitesCount = await dataTable.countRows(); expect(sitesCount).toEqual(9, 'Incorrect number of sites displayed'); - expect(await dataTable.getRowByName(adminSite6).isPresent()).toBe(false, `${adminSite6} should not appear`); + expect(await dataTable.isItemPresent(adminSite6)).toBe(false, `${adminSite6} should not appear`); }); it('Library visibility is correctly displayed - [C289906]', async () => { @@ -216,17 +194,11 @@ describe('File Libraries', () => { [userSitePublic]: SITE_VISIBILITY.PUBLIC }; - const rowCells = await dataTable.getRows().map((row) => { - return row.all(dataTable.cell).map(async cell => await cell.getText()); - }); - const sitesList = rowCells.reduce((acc, cell) => { - acc[cell[1]] = cell[3].toUpperCase(); - return acc; - }, {}); + const sitesList = await dataTable.getSitesNameAndVisibility(); - Object.keys(expectedSitesVisibility).forEach((site) => { + for (const site of Object.keys(expectedSitesVisibility)) { expect(sitesList[site]).toEqual(expectedSitesVisibility[site]); - }); + } }); it('User role is correctly displayed - [C289904]', async () => { @@ -237,17 +209,11 @@ describe('File Libraries', () => { [adminSite4]: SITE_ROLES.SITE_MANAGER.LABEL }; - const rowCells = await dataTable.getRows().map((row) => { - return row.all(dataTable.cell).map(async cell => await cell.getText()); - }); - const sitesList = rowCells.reduce((acc, cell) => { - acc[cell[1]] = cell[2]; - return acc; - }, {}); + const sitesList = await dataTable.getSitesNameAndRole(); - Object.keys(expectedSitesRoles).forEach((site) => { + for (const site of Object.keys(expectedSitesRoles)) { expect(sitesList[site]).toEqual(expectedSitesRoles[site]); - }); + } }); it('Site ID is displayed when two sites have the same name - [C289896]', async () => { diff --git a/e2e/suites/list-views/generic-errors.test.ts b/e2e/suites/list-views/generic-errors.test.ts index 7f5690c17e..92422f035c 100755 --- a/e2e/suites/list-views/generic-errors.test.ts +++ b/e2e/suites/list-views/generic-errors.test.ts @@ -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 diff --git a/e2e/suites/list-views/permissions.test.ts b/e2e/suites/list-views/permissions.test.ts index a4e1fb82e9..081f4286c1 100755 --- a/e2e/suites/list-views/permissions.test.ts +++ b/e2e/suites/list-views/permissions.test.ts @@ -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 @@ -41,8 +41,6 @@ describe('Special permissions', () => { const page = new BrowsingPage(); const { dataTable } = page; - xit(''); - beforeAll(async (done) => { await apis.admin.people.createUser({ username }); done(); @@ -84,7 +82,7 @@ describe('Special permissions', () => { expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items'); await apis.admin.sites.deleteSiteMember(sitePrivate, username); await page.refresh(); - expect(await dataTable.countRows()).toBe(0, 'Incorrect number of items'); + expect(await dataTable.isEmptyList()).toBe(true, 'Items are still displayed'); }); it('on Favorites - [C213227]', async () => { @@ -92,7 +90,7 @@ describe('Special permissions', () => { expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items'); await apis.admin.sites.deleteSiteMember(sitePrivate, username); await page.refresh(); - expect(await dataTable.countRows()).toBe(0, 'Incorrect number of items'); + expect(await dataTable.isEmptyList()).toBe(true, 'Items are still displayed'); }); it('on Shared Files - [C213116]', async () => { @@ -100,7 +98,7 @@ describe('Special permissions', () => { expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items'); await apis.admin.sites.deleteSiteMember(sitePrivate, username); await page.refresh(); - expect(await dataTable.countRows()).toBe(0, 'Incorrect number of items'); + expect(await dataTable.isEmptyList()).toBe(true, 'Items are still displayed'); }); }); diff --git a/e2e/suites/list-views/personal-files.test.ts b/e2e/suites/list-views/personal-files.test.ts index 7bb0752115..3f72219c28 100755 --- a/e2e/suites/list-views/personal-files.test.ts +++ b/e2e/suites/list-views/personal-files.test.ts @@ -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 @@ -65,8 +65,6 @@ describe('Personal Files', () => { done(); }); - xit(''); - describe(`Admin user's personal files`, () => { beforeAll(async (done) => { await loginPage.loginWithAdmin(); @@ -79,8 +77,8 @@ describe('Personal Files', () => { }); it('has Data Dictionary and created content - [C213241]', async () => { - expect(await dataTable.getRowByName('Data Dictionary').isPresent()).toBe(true, 'Data Dictionary not displayed'); - expect(await dataTable.getRowByName(adminFolder).isPresent()).toBe(true, 'admin folder not displayed'); + expect(await dataTable.isItemPresent('Data Dictionary')).toBe(true, 'Data Dictionary not displayed'); + expect(await dataTable.isItemPresent(adminFolder)).toBe(true, 'admin folder not displayed'); }); }); @@ -96,22 +94,18 @@ describe('Personal Files', () => { }); it('has the correct columns - [C217142]', async () => { - const labels = [ 'Name', 'Size', 'Modified', 'Modified by' ]; - const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label)); - - expect(await dataTable.getColumnHeaders().count()).toBe(4 + 1, 'Incorrect number of columns'); + const expectedColumns = [ 'Thumbnail', 'Name', 'Size', 'Modified', 'Modified by' ]; + const actualColumns = await dataTable.getColumnHeadersText(); - await elements.forEach(async (element, index) => { - expect(await element.isPresent()).toBe(true, `"${labels[index]}" is missing`); - }); + expect(actualColumns).toEqual(expectedColumns); }); it('has default sorted column - [C217143]', async () => { - expect(await dataTable.getSortedColumnHeader().getText()).toBe('Modified'); + expect(await dataTable.getSortedColumnHeaderText()).toBe('Modified'); }); it('has user created content - [C213242]', async () => { - expect(await dataTable.getRowByName(userFolder).isPresent()).toBe(true, 'user folder not displayed'); + expect(await dataTable.isItemPresent(userFolder)).toBe(true, 'user folder not displayed'); }); it('navigates to folder - [C213244]', async () => { @@ -121,7 +115,7 @@ describe('Personal Files', () => { await dataTable.waitForHeader(); expect(await browser.getCurrentUrl()).toContain(nodeId, 'Node ID is not in the URL'); - expect(await dataTable.getRowByName(userFile).isPresent()).toBe(true, 'user file is missing'); + expect(await dataTable.isItemPresent(userFile)).toBe(true, 'user file is missing'); }); it('redirects to Personal Files on clicking the link from sidebar - [C213245]', async () => { diff --git a/e2e/suites/list-views/recent-files.test.ts b/e2e/suites/list-views/recent-files.test.ts index 44de6ae22a..c9ee413532 100755 --- a/e2e/suites/list-views/recent-files.test.ts +++ b/e2e/suites/list-views/recent-files.test.ts @@ -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,30 +81,26 @@ describe('Recent Files', () => { }); it('has the correct columns - [C213168]', async () => { - const labels = [ 'Name', 'Location', 'Size', 'Modified' ]; - const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label)); + const expectedColumns = [ 'Thumbnail', 'Name', 'Location', 'Size', 'Modified' ]; + const actualColumns = await dataTable.getColumnHeadersText(); - expect(await dataTable.getColumnHeaders().count()).toBe(4 + 1, 'Incorrect number of columns'); - - await elements.forEach(async (element, index) => { - expect(await element.isPresent()).toBe(true, `"${labels[index]}" is missing`); - }); + expect(actualColumns).toEqual(expectedColumns); }); it('default sorting column - [C213171]', async () => { - expect(await dataTable.getSortedColumnHeader().getText()).toBe('Modified'); + expect(await dataTable.getSortedColumnHeaderText()).toBe('Modified'); expect(await dataTable.getSortingOrder()).toBe('desc'); }); it('displays the files added by the current user in the last 30 days - [C213170]', async () => { expect(await dataTable.countRows()).toEqual(3, 'Incorrect number of files displayed'); - expect(await dataTable.getRowByName(fileName1).isPresent()).toBe(true, `${fileName1} not displayed`); - expect(await dataTable.getRowByName(fileName2).isPresent()).toBe(true, `${fileName2} not displayed`); - expect(await dataTable.getRowByName(fileSite).isPresent()).toBe(true, `${fileSite} not displayed`); + expect(await dataTable.isItemPresent(fileName1)).toBe(true, `${fileName1} not displayed`); + expect(await dataTable.isItemPresent(fileName2)).toBe(true, `${fileName2} not displayed`); + expect(await dataTable.isItemPresent(fileSite)).toBe(true, `${fileSite} not displayed`); }); it(`file not displayed if it's been deleted - [C213174]`, async () => { - expect(await dataTable.getRowByName(fileName3).isPresent()).not.toBe(true, `${fileName3} is displayed`); + expect(await dataTable.isItemPresent(fileName3)).not.toBe(true, `${fileName3} is displayed`); }); it('Location column displays the parent folder of the file - [C213175]', async () => { @@ -114,9 +110,9 @@ describe('Recent Files', () => { }); it('Location column displays a tooltip with the entire path of the file - [C213177]', async () => { - expect(await dataTable.getItemLocationTileAttr(fileName1)).toEqual(`Personal Files/${folderName}`); - expect(await dataTable.getItemLocationTileAttr(fileName2)).toEqual('Personal Files'); - expect(await dataTable.getItemLocationTileAttr(fileSite)).toEqual(`File Libraries/${siteName}/${folderSite}`); + expect(await dataTable.getItemLocationTooltip(fileName1)).toEqual(`Personal Files/${folderName}`); + expect(await dataTable.getItemLocationTooltip(fileName2)).toEqual('Personal Files'); + expect(await dataTable.getItemLocationTooltip(fileSite)).toEqual(`File Libraries/${siteName}/${folderSite}`); }); it('Location column redirect - file in user Home - [C213176]', async () => { diff --git a/e2e/suites/list-views/shared-files.test.ts b/e2e/suites/list-views/shared-files.test.ts index 94896fe2bf..c0c0a447fd 100755 --- a/e2e/suites/list-views/shared-files.test.ts +++ b/e2e/suites/list-views/shared-files.test.ts @@ -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 @@ -87,12 +87,10 @@ describe('Shared Files', () => { }); it('has the correct columns - [C213113]', async () => { - const expectedHeader = [ 'Thumbnail', 'Name', 'Location', 'Size', 'Modified', 'Modified by', 'Shared by' ]; - const headers = dataTable.getColumnHeaders(); - const count = await headers.count(); - expect(count).toBe(6 + 1, 'Incorrect number of columns'); + const expectedColumns = [ 'Thumbnail', 'Name', 'Location', 'Size', 'Modified', 'Modified by', 'Shared by' ]; + const actualColumns = await dataTable.getColumnHeadersText(); - expect(await dataTable.getHeaderText()).toEqual(expectedHeader); + expect(actualColumns).toEqual(expectedColumns); }); it('default sorting column - [C213115]', async () => { @@ -101,20 +99,20 @@ describe('Shared Files', () => { }); it('displays the files shared by everyone - [C213114]', async () => { - expect(await dataTable.getRowByName(fileAdmin).isPresent()).toBe(true, `${fileAdmin} not displayed`); - expect(await dataTable.getRowByName(file1User).isPresent()).toBe(true, `${file1User} not displayed`); + expect(await dataTable.isItemPresent(fileAdmin)).toBe(true, `${fileAdmin} not displayed`); + expect(await dataTable.isItemPresent(file1User)).toBe(true, `${file1User} not displayed`); }); it(`file not displayed if it's been deleted - [C213117]`, async () => { - expect(await dataTable.getRowByName(file2User).isPresent()).toBe(false, `${file2User} is displayed`); + expect(await dataTable.isItemPresent(file2User)).toBe(false, `${file2User} is displayed`); }); it('unshared file is not displayed - [C213118]', async () => { - expect(await dataTable.getRowByName(file3User).isPresent()).toBe(false, `${file3User} is displayed`); + expect(await dataTable.isItemPresent(file3User)).toBe(false, `${file3User} is displayed`); }); it('Location column displays the parent folder of the file - [C213665]', async () => { - expect(await dataTable.getItemLocationTileAttr(file4User)).toEqual('Personal Files'); + expect(await dataTable.getItemLocationTooltip(file4User)).toEqual('Personal Files'); expect(await dataTable.getItemLocation(fileAdmin)).toEqual(siteName); expect(await dataTable.getItemLocation(file1User)).toEqual(folderUser); }); @@ -135,7 +133,7 @@ describe('Shared Files', () => { }); it('Location column displays a tooltip with the entire path of the file - [C213667]', async () => { - expect(await dataTable.getItemLocationTileAttr(fileAdmin)).toEqual(`File Libraries/${siteName}`); - expect(await dataTable.getItemLocationTileAttr(file1User)).toEqual(`Personal Files/${folderUser}`); + expect(await dataTable.getItemLocationTooltip(fileAdmin)).toEqual(`File Libraries/${siteName}`); + expect(await dataTable.getItemLocationTooltip(file1User)).toEqual(`Personal Files/${folderUser}`); }); }); diff --git a/e2e/suites/list-views/tooltips.test.ts b/e2e/suites/list-views/tooltips.test.ts index dfb60346be..53499c6599 100755 --- a/e2e/suites/list-views/tooltips.test.ts +++ b/e2e/suites/list-views/tooltips.test.ts @@ -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 @@ -85,8 +85,6 @@ describe('File / folder tooltips', () => { done(); }); - xit(''); - describe('on Personal Files', () => { beforeAll(async (done) => { await page.clickPersonalFilesAndWait(); diff --git a/e2e/suites/list-views/trash.test.ts b/e2e/suites/list-views/trash.test.ts index 8ad7a4437c..63216feb62 100755 --- a/e2e/suites/list-views/trash.test.ts +++ b/e2e/suites/list-views/trash.test.ts @@ -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 @@ -87,8 +87,6 @@ describe('Trash', () => { done(); }); - xit(''); - describe('as admin', () => { beforeAll(async (done) => { await loginPage.loginWithAdmin(); @@ -101,24 +99,20 @@ describe('Trash', () => { }); it('has the correct columns - [C213217]', async () => { - const labels = [ 'Name', 'Location', 'Size', 'Deleted', 'Deleted by' ]; - const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label)); - - expect(await dataTable.getColumnHeaders().count()).toBe(5 + 1, 'Incorrect number of columns'); + const expectedColumns = [ 'Thumbnail', 'Name', 'Location', 'Size', 'Deleted', 'Deleted by' ]; + const actualColumns = await dataTable.getColumnHeadersText(); - await elements.forEach(async (element, index) => { - expect(await element.isPresent()).toBe(true, `"${labels[index]}" is missing`); - }); + expect(actualColumns).toEqual(expectedColumns); }); it('displays the files and folders deleted by everyone - [C280493]', async () => { expect(await dataTable.countRows()).toEqual(8, 'Incorrect number of deleted items displayed'); - expect(await dataTable.getRowByName(fileAdmin).isPresent()).toBe(true, `${fileAdmin} not displayed`); - expect(await dataTable.getRowByName(folderAdmin).isPresent()).toBe(true, `${folderAdmin} not displayed`); - expect(await dataTable.getRowByName(fileUser).isPresent()).toBe(true, `${fileUser} not displayed`); - expect(await dataTable.getRowByName(folderUser).isPresent()).toBe(true, `${folderUser} not displayed`); - expect(await dataTable.getRowByName(fileSite).isPresent()).toBe(true, `${fileSite} not displayed`); + expect(await dataTable.isItemPresent(fileAdmin)).toBe(true, `${fileAdmin} not displayed`); + expect(await dataTable.isItemPresent(folderAdmin)).toBe(true, `${folderAdmin} not displayed`); + expect(await dataTable.isItemPresent(fileUser)).toBe(true, `${fileUser} not displayed`); + expect(await dataTable.isItemPresent(folderUser)).toBe(true, `${folderUser} not displayed`); + expect(await dataTable.isItemPresent(fileSite)).toBe(true, `${fileSite} not displayed`); }); }); @@ -134,27 +128,23 @@ describe('Trash', () => { }); it('has the correct columns - [C280494]', async () => { - const labels = [ 'Name', 'Location', 'Size', 'Deleted']; - const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label)); - - expect(await dataTable.getColumnHeaders().count()).toBe(4 + 1, 'Incorrect number of columns'); + const expectedColumns = [ 'Thumbnail', 'Name', 'Location', 'Size', 'Deleted']; + const actualColumns = await dataTable.getColumnHeadersText(); - await elements.forEach(async (element, index) => { - expect(await element.isPresent()).toBe(true, `"${labels[index]}" is missing`); - }); + expect(actualColumns).toEqual(expectedColumns); }); it('displays the files and folders deleted by the user - [C213218]', async () => { expect(await dataTable.countRows()).toEqual(6, 'Incorrect number of deleted items displayed'); - expect(await dataTable.getRowByName(fileSite).isPresent()).toBe(true, `${fileSite} not displayed`); - expect(await dataTable.getRowByName(fileUser).isPresent()).toBe(true, `${fileUser} not displayed`); - expect(await dataTable.getRowByName(folderUser).isPresent()).toBe(true, `${folderUser} not displayed`); - expect(await dataTable.getRowByName(fileAdmin).isPresent()).toBe(false, `${fileAdmin} is displayed`); + expect(await dataTable.isItemPresent(fileSite)).toBe(true, `${fileSite} not displayed`); + expect(await dataTable.isItemPresent(fileUser)).toBe(true, `${fileUser} not displayed`); + expect(await dataTable.isItemPresent(folderUser)).toBe(true, `${folderUser} not displayed`); + expect(await dataTable.isItemPresent(fileAdmin)).toBe(false, `${fileAdmin} is displayed`); }); it('default sorting column - [C213219]', async () => { - expect(await dataTable.getSortedColumnHeader().getText()).toBe('Deleted'); + expect(await dataTable.getSortedColumnHeaderText()).toBe('Deleted'); expect(await dataTable.getSortingOrder()).toBe('desc'); }); @@ -165,9 +155,9 @@ describe('Trash', () => { }); it('Location column displays a tooltip with the entire path of the file - [C280499]', async () => { - expect(await dataTable.getItemLocationTileAttr(fileInFolder)).toEqual(`Personal Files/${folderNotDeleted}`); - expect(await dataTable.getItemLocationTileAttr(fileUser)).toEqual('Personal Files'); - expect(await dataTable.getItemLocationTileAttr(fileSite)).toEqual(`File Libraries/${siteName}`); + expect(await dataTable.getItemLocationTooltip(fileInFolder)).toEqual(`Personal Files/${folderNotDeleted}`); + expect(await dataTable.getItemLocationTooltip(fileUser)).toEqual('Personal Files'); + expect(await dataTable.getItemLocationTooltip(fileSite)).toEqual(`File Libraries/${siteName}`); }); it('Location column is empty if parent folder no longer exists - [C280500]', async () => { diff --git a/e2e/suites/navigation/breadcrumb.test.ts b/e2e/suites/navigation/breadcrumb.test.ts index 5e5abf4ac2..198870a5aa 100755 --- a/e2e/suites/navigation/breadcrumb.test.ts +++ b/e2e/suites/navigation/breadcrumb.test.ts @@ -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 @@ -90,13 +90,13 @@ describe('Breadcrumb', () => { }); it('My Libraries breadcrumb main node - [C260966]', async () => { - await page.goToMyLibraries(); + await page.goToMyLibrariesAndWait(); expect(await breadcrumb.getItemsCount()).toEqual(1, 'Breadcrumb has incorrect number of items'); expect(await breadcrumb.getCurrentItemName()).toBe('My Libraries'); }); it('Favorite Libraries breadcrumb main node - [C289891]', async () => { - await page.goToFavoriteLibraries(); + await page.goToFavoriteLibrariesAndWait(); expect(await breadcrumb.getItemsCount()).toEqual(1, 'Breadcrumb has incorrect number of items'); expect(await breadcrumb.getCurrentItemName()).toBe('Favorite Libraries'); }); @@ -185,9 +185,8 @@ describe('Breadcrumb', () => { expect(await breadcrumb.getAllItems()).toEqual(expectedBreadcrumb); }); - // disabled cause of ACA-1039 - xdescribe('as admin', () => { - const user2 = 'a_user'; + describe('as admin', () => { + const user2 = `user2-${Utils.random()}`; const userFolder = `userFolder-${Utils.random()}`; let userFolderId; const user2Api = new RepoClient(user2, user2); @@ -203,7 +202,7 @@ describe('Breadcrumb', () => { done(); }); - xit(`Breadcrumb on navigation to a user's home - [C260970]`, async () => { + it(`Breadcrumb on navigation to a user's home - [C260970]`, async () => { await page.dataTable.doubleClickOnRowByName('User Homes'); await page.dataTable.doubleClickOnRowByName(user2); expect(await breadcrumb.getAllItems()).toEqual([ 'Personal Files', 'User Homes', user2 ]); diff --git a/e2e/suites/navigation/sidebar.test.ts b/e2e/suites/navigation/sidebar.test.ts index 0c9700206c..83a47645a3 100755 --- a/e2e/suites/navigation/sidebar.test.ts +++ b/e2e/suites/navigation/sidebar.test.ts @@ -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 @@ -24,23 +24,31 @@ */ import { browser } from 'protractor'; - import { APP_ROUTES, SIDEBAR_LABELS } from '../../configs'; -import { LoginPage, BrowsingPage } from '../../pages/pages'; +import { LoginPage, BrowsingPage, SearchResultsPage } from '../../pages/pages'; +import { Utils } from '../../utilities/utils'; describe('Sidebar', () => { const loginPage = new LoginPage(); const page = new BrowsingPage(); - const { sidenav } = page; + const { sidenav, header } = page; + const searchResultsPage = new SearchResultsPage(); + const { searchInput } = searchResultsPage.header; beforeAll(async (done) => { await loginPage.loginWithAdmin(); done(); }); + beforeEach(async (done) => { + await Utils.pressEscape(); + await header.expandSideNav(); + done(); + }); + it('has "Personal Files" as default - [C217149]', async () => { expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES); - expect(await sidenav.isActive(SIDEBAR_LABELS.PERSONAL_FILES)).toBe(true, 'Active link'); + expect(await sidenav.isActive(SIDEBAR_LABELS.PERSONAL_FILES)).toBe(true, 'Default active link'); }); it('File Libraries has correct sub-categories - [C217150]', async () => { @@ -51,32 +59,26 @@ describe('Sidebar', () => { }); it('My Libraries is automatically selected on expanding File Libraries - [C289900]', async () => { - await page.clickFileLibraries(); + await sidenav.expandFileLibraries(); expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.MY_LIBRARIES); - expect(await sidenav.isActive(SIDEBAR_LABELS.FILE_LIBRARIES)).toBe(true, 'File Libraries link not active'); + expect(await sidenav.isActive(SIDEBAR_LABELS.FILE_LIBRARIES)).toBe(false, 'File Libraries link is active'); expect(await sidenav.childIsActive(SIDEBAR_LABELS.MY_LIBRARIES)).toBe(true, 'My Libraries link not active'); }); it('navigate to Favorite Libraries - [C289902]', async () => { await page.goToFavoriteLibraries(); expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.FAVORITE_LIBRARIES); - expect(await sidenav.isActive(SIDEBAR_LABELS.FILE_LIBRARIES)).toBe(true, 'File Libraries link not active'); + expect(await sidenav.isActive(SIDEBAR_LABELS.FILE_LIBRARIES)).toBe(false, 'File Libraries link is active'); expect(await sidenav.childIsActive(SIDEBAR_LABELS.FAVORITE_LIBRARIES)).toBe(true, 'Favorite Libraries link not active'); }); it('navigate to My Libraries - [C289901]', async () => { await page.goToMyLibraries(); expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.MY_LIBRARIES); - expect(await sidenav.isActive(SIDEBAR_LABELS.FILE_LIBRARIES)).toBe(true, 'File Libraries link not active'); + expect(await sidenav.isActive(SIDEBAR_LABELS.FILE_LIBRARIES)).toBe(false, 'File Libraries link is active'); expect(await sidenav.childIsActive(SIDEBAR_LABELS.MY_LIBRARIES)).toBe(true, 'My Libraries link not active'); }); - it('navigates to "Personal Files" - [C280409]', async () => { - await page.clickPersonalFiles(); - expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES); - expect(await sidenav.isActive(SIDEBAR_LABELS.PERSONAL_FILES)).toBe(true, 'Personal Files link not active'); - }); - it('navigates to "Shared Files" - [C213110]', async () => { await page.clickSharedFiles(); expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.SHARED_FILES); @@ -101,51 +103,135 @@ describe('Sidebar', () => { expect(await sidenav.isActive(SIDEBAR_LABELS.TRASH)).toBe(true, 'Trash link not active'); }); - // TODO: incomplete test + it('navigates to "Personal Files" - [C280409]', async () => { + await page.clickPersonalFiles(); + expect(await browser.getCurrentUrl()).toContain(APP_ROUTES.PERSONAL_FILES); + expect(await sidenav.isActive(SIDEBAR_LABELS.PERSONAL_FILES)).toBe(true, 'Personal Files link not active'); + }); + it('Personal Files tooltip - [C217151]', async () => { await page.clickPersonalFiles(); expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.PERSONAL_FILES)).toContain('View your Personal Files'); + + await header.collapseSideNav(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.PERSONAL_FILES)).toContain('View your Personal Files'); + }); + + it('Shared Files tooltip - [C213111]', async () => { + await page.clickSharedFiles(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.SHARED_FILES)).toContain('View files that have been shared'); + + await header.collapseSideNav(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.SHARED_FILES)).toContain('View files that have been shared'); + }); + + it('Recent Files tooltip - [C213167]', async () => { + await page.clickRecentFiles(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.RECENT_FILES)).toContain('View files you recently edited'); + + await header.collapseSideNav(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.RECENT_FILES)).toContain('View files you recently edited'); + }); + + it('Favorites tooltip - [C217153]', async () => { + await page.clickFavorites(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FAVORITES)).toContain('View your favorite files and folders'); + + await header.collapseSideNav(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FAVORITES)).toContain('View your favorite files and folders'); + }); + + it('Trash tooltip - [C217154]', async () => { + await page.clickTrash(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.TRASH)).toContain('View deleted files in the trash'); + + await header.collapseSideNav(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.TRASH)).toContain('View deleted files in the trash'); }); - // TODO: incomplete test it('File Libraries tooltip - [C217152]', async () => { await page.clickFileLibraries(); expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FILE_LIBRARIES)).toContain('File Libraries'); + + await header.collapseSideNav(); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FILE_LIBRARIES)).toContain('File Libraries'); }); - // TODO: incomplete test it('My Libraries tooltip - [C289916]', async () => { await page.goToMyLibraries(); expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.MY_LIBRARIES)).toContain('Access my libraries'); + + await header.collapseSideNav(); + await sidenav.clickLink(SIDEBAR_LABELS.FILE_LIBRARIES); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.MY_LIBRARIES)).toContain('Access my libraries'); }); - // TODO: incomplete test it('Favorite Libraries tooltip - [C289917]', async () => { await page.goToFavoriteLibraries(); expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FAVORITE_LIBRARIES)).toContain('Access my favorite libraries'); + + await header.collapseSideNav(); + await sidenav.clickLink(SIDEBAR_LABELS.FILE_LIBRARIES); + expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FAVORITE_LIBRARIES)).toContain('Access my favorite libraries'); }); - // TODO: incomplete test - it('Shared Files tooltip - [C213111]', async () => { - await page.clickSharedFiles(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.SHARED_FILES)).toContain('View files that have been shared'); + it('default state is expanded - [C269095]', async () => { + expect(await header.isExpandedSidenav()).toBe(true, 'Sidebar not expanded'); }); - // TODO: incomplete test - it('Recent Files tooltip - [C213167]', async () => { - await page.clickRecentFiles(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.RECENT_FILES)).toContain('View files you recently edited'); + it('sidebar toggle - [C269096]', async () => { + await header.collapseSideNav(); + expect(await header.isExpandedSidenav()).toBe(false, 'Sidebar not collapsed'); + + await header.expandSideNav(); + expect(await header.isExpandedSidenav()).toBe(true, 'Sidebar not expanded'); }); - // TODO: incomplete test - it('Favorites tooltip - [C217153]', async () => { + it('sidebar state is preserved on page refresh - [C269100]', async () => { + expect(await header.isExpandedSidenav()).toBe(true, 'Sidebar not expanded'); + await page.refresh(); + expect(await header.isExpandedSidenav()).toBe(true, 'Sidebar not expanded'); + + await header.collapseSideNav(); + expect(await header.isExpandedSidenav()).toBe(false, 'Sidebar not collapsed'); + await page.refresh(); + expect(await header.isExpandedSidenav()).toBe(false, 'Sidebar not collapsed'); + }); + + it('sidebar state is preserved after logout / login - [C269102]', async () => { + await header.collapseSideNav(); + await page.signOut(); + await loginPage.loginWithAdmin(); + + expect(await header.isExpandedSidenav()).toBe(false, 'Sidebar not collapsed'); + }); + + it('sidebar is collapsed automatically when Search Results opens - [C277223]', async () => { + await searchInput.clickSearchButton(); + /* cspell:disable-next-line */ + await searchInput.searchForTextAndCloseSearchOptions('qwertyuiop'); + await searchResultsPage.waitForResults(); + + expect(await header.isExpandedSidenav()).toBe(false, 'Sidebar not collapsed'); + }); + + it('sidenav returns to the default state when navigating away from the Search Results page - [C277224]', async () => { + await searchInput.clickSearchButton(); + /* cspell:disable-next-line */ + await searchInput.searchForTextAndCloseSearchOptions('qwertyuiop'); + await searchResultsPage.waitForResults(); await page.clickFavorites(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.FAVORITES)).toContain('View your favorite files and folders'); + + expect(await header.isExpandedSidenav()).toBe(true, 'Sidebar not expanded'); }); - // TODO: incomplete test - it('Trash tooltip - [C217154]', async () => { - await page.clickTrash(); - expect(await sidenav.getLinkTooltip(SIDEBAR_LABELS.TRASH)).toContain('View deleted files in the trash'); + it('sidenav can be expanded when search results page is displayed - [C277230]', async () => { + await searchInput.clickSearchButton(); + /* cspell:disable-next-line */ + await searchInput.searchForTextAndCloseSearchOptions('qwertyuiop'); + await searchResultsPage.waitForResults(); + await header.expandSideNav(); + + expect(await header.isExpandedSidenav()).toBe(true, 'Sidebar not expanded'); }); }); diff --git a/e2e/suites/pagination/pag-favorites.test.ts b/e2e/suites/pagination/pag-favorites.test.ts index 5eb438bfef..95b0a804e3 100755 --- a/e2e/suites/pagination/pag-favorites.test.ts +++ b/e2e/suites/pagination/pag-favorites.test.ts @@ -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 @@ -73,12 +73,12 @@ describe('Pagination on multiple pages on Favorites', () => { }); it('Pagination control default values - [C280113]', async () => { - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await pagination.maxItems.getText()).toContain('25'); - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.totalPages.getText()).toContain('of 5'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.getTotalPages()).toContain('of 5'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); }); it('Items per page values - [C280114]', async () => { @@ -94,24 +94,24 @@ describe('Pagination on multiple pages on Favorites', () => { it('current page menu items - [C280115]', async () => { await pagination.openMaxItemsMenu() await pagination.menu.clickMenuItem('25'); - expect(await pagination.getText(pagination.maxItems)).toContain('25'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 5'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getTotalPages()).toContain('of 5'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(5); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('50'); - expect(await pagination.getText(pagination.maxItems)).toContain('50'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 3'); + expect(await pagination.getMaxItems()).toContain('50'); + expect(await pagination.getTotalPages()).toContain('of 3'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(3); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('100'); - expect(await pagination.getText(pagination.maxItems)).toContain('100'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 2'); + expect(await pagination.getMaxItems()).toContain('100'); + expect(await pagination.getTotalPages()).toContain('of 2'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(2); await pagination.menu.closeMenu(); @@ -122,43 +122,43 @@ describe('Pagination on multiple pages on Favorites', () => { it('change the current page from menu - [C280116]', async () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(3); - expect(await pagination.getText(pagination.range)).toContain('51-75 of 101'); - expect(await pagination.getText(pagination.currentPage)).toContain('Page 3'); - expect(await pagination.previousButton.isEnabled()).toBe(true, 'Previous button is not enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); - expect(await dataTable.getRowByName('file-40').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('51-75 of 101'); + expect(await pagination.getCurrentPage()).toContain('Page 3'); + expect(await pagination.isPreviousEnabled()).toBe(true, 'Previous button is not enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + expect(await dataTable.isItemPresent('file-40')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); it('navigate to next and previous pages - [C280119]', async () => { - await pagination.nextButton.click(); + await pagination.clickNext(); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('26-50 of 101'); - expect(await dataTable.getRowByName('file-70').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('26-50 of 101'); + expect(await dataTable.isItemPresent('file-70')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(2); await dataTable.waitForHeader(); - await pagination.previousButton.click(); + await pagination.clickPrevious(); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await dataTable.getRowByName('file-88').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await dataTable.isItemPresent('file-88')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); it('Previous button is disabled on first page - [C280117]', async () => { - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled on first page'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled on first page'); }); it('Next button is disabled on last page - [C280118]', async () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(5); expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); - expect(await pagination.currentPage.getText()).toContain('Page 5'); - expect(await pagination.nextButton.isEnabled()).toBe(false, 'Next button is enabled on last page'); + expect(await pagination.getCurrentPage()).toContain('Page 5'); + expect(await pagination.isNextEnabled()).toBe(false, 'Next button is enabled on last page'); }); }); diff --git a/e2e/suites/pagination/pag-file-libraries.test.ts b/e2e/suites/pagination/pag-file-libraries.test.ts index 0146330140..a042c1f5b9 100755 --- a/e2e/suites/pagination/pag-file-libraries.test.ts +++ b/e2e/suites/pagination/pag-file-libraries.test.ts @@ -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,7 +28,7 @@ import { LoginPage, BrowsingPage } from '../../pages/pages'; import { Utils } from '../../utilities/utils'; import { RepoClient } from '../../utilities/repo-client/repo-client'; -describe('Pagination on multiple pages on File Libraries', () => { +describe('Pagination on multiple pages', () => { const username = `user-${Utils.random()}`; const apis = { @@ -51,109 +51,215 @@ describe('Pagination on multiple pages on File Libraries', () => { done(); }); - beforeEach(async (done) => { - await page.clickFileLibrariesAndWait(); - done(); - }); - - afterEach(async (done) => { - await Utils.pressEscape(); - done(); - }); - afterAll(async (done) => { await apis.user.sites.deleteSites(sites); done(); }) - it('Pagination control default values - [C280086]', async () => { - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await pagination.maxItems.getText()).toContain('25'); - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.totalPages.getText()).toContain('of 5'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); - }); + describe('on My Libraries', () => { + beforeEach(async (done) => { + await page.goToMyLibrariesAndWait(); + done(); + }); - it('Items per page values - [C280087]', async () => { - await pagination.openMaxItemsMenu(); - const [ first, second, third ] = [1, 2, 3] - .map(async nth => await pagination.menu.getNthItem(nth).getText()); - expect(first).toBe('25'); - expect(second).toBe('50'); - expect(third).toBe('100'); - await pagination.menu.closeMenu(); - }); + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); - it('current page menu items - [C280088]', async () => { - await pagination.openMaxItemsMenu(); - await pagination.menu.clickMenuItem('25'); - expect(await pagination.getText(pagination.maxItems)).toContain('25'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 5'); - await pagination.openCurrentPageMenu(); - expect(await pagination.menu.getItemsCount()).toBe(5); - await pagination.menu.closeMenu(); - - await pagination.openMaxItemsMenu(); - await pagination.menu.clickMenuItem('50'); - expect(await pagination.getText(pagination.maxItems)).toContain('50'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 3'); - await pagination.openCurrentPageMenu(); - expect(await pagination.menu.getItemsCount()).toBe(3); - await pagination.menu.closeMenu(); - - await pagination.openMaxItemsMenu(); - await pagination.menu.clickMenuItem('100'); - expect(await pagination.getText(pagination.maxItems)).toContain('100'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 2'); - await pagination.openCurrentPageMenu(); - expect(await pagination.menu.getItemsCount()).toBe(2); - await pagination.menu.closeMenu(); - - await pagination.resetToDefaultPageSize(); - }); + it('Pagination control default values - [C280086]', async () => { + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.getTotalPages()).toContain('of 5'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + }); - it('change the current page from menu - [C280089]', async () => { - await pagination.openCurrentPageMenu(); - await pagination.menu.clickNthItem(3); - await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('51-75 of 101'); - expect(await pagination.currentPage.getText()).toContain('Page 3'); - expect(await pagination.previousButton.isEnabled()).toBe(true, 'Previous button is not enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); - expect(await dataTable.getRowByName('site-60').isPresent()).toBe(true, 'Site-60 not found on page'); - - await pagination.resetToDefaultPageNumber(); - }); + it('Items per page values - [C280087]', async () => { + await pagination.openMaxItemsMenu(); + const [ first, second, third ] = [1, 2, 3] + .map(async nth => await pagination.menu.getNthItem(nth).getText()); + expect(first).toBe('25'); + expect(second).toBe('50'); + expect(third).toBe('100'); + await pagination.menu.closeMenu(); + }); - it('navigate to next and previous pages - [C280092]', async () => { - await pagination.clickNext(); - await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('26-50 of 101'); - expect(await dataTable.getRowByName('site-31').isPresent()).toBe(true, 'Site-31 not found on page'); - await pagination.resetToDefaultPageNumber(); - - await pagination.openCurrentPageMenu(); - await pagination.menu.clickNthItem(2); - await dataTable.waitForHeader(); - await pagination.previousButton.click(); - await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await dataTable.getRowByName('site-12').isPresent()).toBe(true, 'Site-12 not found on page'); - - await pagination.resetToDefaultPageNumber(); - }); + it('current page menu items - [C280088]', async () => { + await pagination.openMaxItemsMenu(); + await pagination.menu.clickMenuItem('25'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getTotalPages()).toContain('of 5'); + await pagination.openCurrentPageMenu(); + expect(await pagination.menu.getItemsCount()).toBe(5); + await pagination.menu.closeMenu(); + + await pagination.openMaxItemsMenu(); + await pagination.menu.clickMenuItem('50'); + expect(await pagination.getMaxItems()).toContain('50'); + expect(await pagination.getTotalPages()).toContain('of 3'); + await pagination.openCurrentPageMenu(); + expect(await pagination.menu.getItemsCount()).toBe(3); + await pagination.menu.closeMenu(); + + await pagination.openMaxItemsMenu(); + await pagination.menu.clickMenuItem('100'); + expect(await pagination.getMaxItems()).toContain('100'); + expect(await pagination.getTotalPages()).toContain('of 2'); + await pagination.openCurrentPageMenu(); + expect(await pagination.menu.getItemsCount()).toBe(2); + await pagination.menu.closeMenu(); + + await pagination.resetToDefaultPageSize(); + }); + + it('change the current page from menu - [C280089]', async () => { + await pagination.openCurrentPageMenu(); + await pagination.menu.clickNthItem(3); + await dataTable.waitForHeader(); + expect(await pagination.getRange()).toContain('51-75 of 101'); + expect(await pagination.getCurrentPage()).toContain('Page 3'); + expect(await pagination.isPreviousEnabled()).toBe(true, 'Previous button is not enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + expect(await dataTable.isItemPresent('site-60')).toBe(true, 'Site-60 not found on page'); + + await pagination.resetToDefaultPageNumber(); + }); + + it('navigate to next and previous pages - [C280092]', async () => { + await pagination.clickNext(); + await dataTable.waitForHeader(); + expect(await pagination.getRange()).toContain('26-50 of 101'); + expect(await dataTable.isItemPresent('site-31')).toBe(true, 'Site-31 not found on page'); + await pagination.resetToDefaultPageNumber(); + + await pagination.openCurrentPageMenu(); + await pagination.menu.clickNthItem(2); + await dataTable.waitForHeader(); + await pagination.clickPrevious(); + await dataTable.waitForHeader(); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await dataTable.isItemPresent('site-12')).toBe(true, 'Site-12 not found on page'); - it('Previous button is disabled on first page - [C280090]', async () => { - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled on first page'); + await pagination.resetToDefaultPageNumber(); + }); + + it('Previous button is disabled on first page - [C280090]', async () => { + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled on first page'); + }); + + it('Next button is disabled on last page - [C280091]', async () => { + await pagination.openCurrentPageMenu(); + await pagination.menu.clickNthItem(5); + expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); + expect(await pagination.getCurrentPage()).toContain('Page 5'); + expect(await pagination.isNextEnabled()).toBe(false, 'Next button is enabled on last page'); + }); }); - it('Next button is disabled on last page - [C280091]', async () => { - await pagination.openCurrentPageMenu(); - await pagination.menu.clickNthItem(5); - expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); - expect(await pagination.currentPage.getText()).toContain('Page 5'); - expect(await pagination.nextButton.isEnabled()).toBe(false, 'Next button is enabled on last page'); + describe('on Favorite Libraries', () => { + beforeEach(async (done) => { + await page.goToFavoriteLibrariesAndWait(); + done(); + }); + + afterEach(async (done) => { + await Utils.pressEscape(); + done(); + }); + + it('Pagination control default values - [C291875]', async () => { + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.getTotalPages()).toContain('of 5'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + }); + + it('Items per page values - [C291876]', async () => { + await pagination.openMaxItemsMenu(); + const [ first, second, third ] = [1, 2, 3] + .map(async nth => await pagination.menu.getNthItem(nth).getText()); + expect(first).toBe('25'); + expect(second).toBe('50'); + expect(third).toBe('100'); + await pagination.menu.closeMenu(); + }); + + it('current page menu items - [C291877]', async () => { + await pagination.openMaxItemsMenu(); + await pagination.menu.clickMenuItem('25'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getTotalPages()).toContain('of 5'); + await pagination.openCurrentPageMenu(); + expect(await pagination.menu.getItemsCount()).toBe(5); + await pagination.menu.closeMenu(); + + await pagination.openMaxItemsMenu(); + await pagination.menu.clickMenuItem('50'); + expect(await pagination.getMaxItems()).toContain('50'); + expect(await pagination.getTotalPages()).toContain('of 3'); + await pagination.openCurrentPageMenu(); + expect(await pagination.menu.getItemsCount()).toBe(3); + await pagination.menu.closeMenu(); + + await pagination.openMaxItemsMenu(); + await pagination.menu.clickMenuItem('100'); + expect(await pagination.getMaxItems()).toContain('100'); + expect(await pagination.getTotalPages()).toContain('of 2'); + await pagination.openCurrentPageMenu(); + expect(await pagination.menu.getItemsCount()).toBe(2); + await pagination.menu.closeMenu(); + + await pagination.resetToDefaultPageSize(); + }); + + it('change the current page from menu - [C291878]', async () => { + await pagination.openCurrentPageMenu(); + await pagination.menu.clickNthItem(3); + await dataTable.waitForHeader(); + expect(await pagination.getRange()).toContain('51-75 of 101'); + expect(await pagination.getCurrentPage()).toContain('Page 3'); + expect(await pagination.isPreviousEnabled()).toBe(true, 'Previous button is not enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + expect(await dataTable.isItemPresent('site-40')).toBe(true, 'Site-60 not found on page'); + + await pagination.resetToDefaultPageNumber(); + }); + + it('navigate to next and previous pages - [C291881]', async () => { + await pagination.clickNext(); + await dataTable.waitForHeader(); + expect(await pagination.getRange()).toContain('26-50 of 101'); + expect(await dataTable.isItemPresent('site-70')).toBe(true, 'Site-31 not found on page'); + await pagination.resetToDefaultPageNumber(); + + await pagination.openCurrentPageMenu(); + await pagination.menu.clickNthItem(2); + await dataTable.waitForHeader(); + await pagination.clickPrevious(); + await dataTable.waitForHeader(); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await dataTable.isItemPresent('site-88')).toBe(true, 'Site-12 not found on page'); + + await pagination.resetToDefaultPageNumber(); + }); + + it('Previous button is disabled on first page - [C291879]', async () => { + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled on first page'); + }); + + it('Next button is disabled on last page - [C291880]', async () => { + await pagination.openCurrentPageMenu(); + await pagination.menu.clickNthItem(5); + expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); + expect(await pagination.getCurrentPage()).toContain('Page 5'); + expect(await pagination.isNextEnabled()).toBe(false, 'Next button is enabled on last page'); + }); }); + }); diff --git a/e2e/suites/pagination/pag-personal-files.test.ts b/e2e/suites/pagination/pag-personal-files.test.ts index 488783b174..eeef6ea253 100755 --- a/e2e/suites/pagination/pag-personal-files.test.ts +++ b/e2e/suites/pagination/pag-personal-files.test.ts @@ -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,12 +69,12 @@ describe('Pagination on multiple pages on Personal Files', () => { }); it('Pagination control default values - [C280077]', async () => { - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await pagination.maxItems.getText()).toContain('25'); - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.totalPages.getText()).toContain('of 5'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.getTotalPages()).toContain('of 5'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); }); it('Items per page values - [C280078]', async () => { @@ -90,24 +90,24 @@ describe('Pagination on multiple pages on Personal Files', () => { it('current page menu items - [C280079]', async () => { await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('25'); - expect(await pagination.getText(pagination.maxItems)).toContain('25'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 5'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getTotalPages()).toContain('of 5'); await pagination.openCurrentPageMenu(); expect(pagination.menu.getItemsCount()).toBe(5); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('50'); - expect(await pagination.getText(pagination.maxItems)).toContain('50'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 3'); + expect(await pagination.getMaxItems()).toContain('50'); + expect(await pagination.getTotalPages()).toContain('of 3'); await pagination.openCurrentPageMenu(); expect(pagination.menu.getItemsCount()).toBe(3); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('100'); - expect(await pagination.getText(pagination.maxItems)).toContain('100'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 2'); + expect(await pagination.getMaxItems()).toContain('100'); + expect(await pagination.getTotalPages()).toContain('of 2'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(2); await pagination.menu.closeMenu(); @@ -119,11 +119,11 @@ describe('Pagination on multiple pages on Personal Files', () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(3); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('51-75 of 101'); - expect(await pagination.currentPage.getText()).toContain('Page 3'); - expect(await pagination.previousButton.isEnabled()).toBe(true, 'Previous button is not enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); - expect(await dataTable.getRowByName('file-60').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('51-75 of 101'); + expect(await pagination.getCurrentPage()).toContain('Page 3'); + expect(await pagination.isPreviousEnabled()).toBe(true, 'Previous button is not enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + expect(await dataTable.isItemPresent('file-60')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); @@ -131,31 +131,31 @@ describe('Pagination on multiple pages on Personal Files', () => { it('navigate to next and previous pages - [C280083]', async () => { await pagination.clickNext(); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('26-50 of 101'); - expect(await dataTable.getRowByName('file-31').isPresent()).toBe(true, 'file-31 not found on page'); + expect(await pagination.getRange()).toContain('26-50 of 101'); + expect(await dataTable.isItemPresent('file-31')).toBe(true, 'file-31 not found on page'); await pagination.resetToDefaultPageNumber(); await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(2); await dataTable.waitForHeader(); - await pagination.previousButton.click(); + await pagination.clickPrevious(); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await dataTable.getRowByName('file-12').isPresent()).toBe(true, 'file-12 not found on page'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await dataTable.isItemPresent('file-12')).toBe(true, 'file-12 not found on page'); await pagination.resetToDefaultPageNumber(); }); it('Previous button is disabled on first page - [C280081]', async () => { - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled on first page'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled on first page'); }); it('Next button is disabled on last page - [C280082]', async () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(5); expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); - expect(await pagination.currentPage.getText()).toContain('Page 5'); - expect(await pagination.nextButton.isEnabled()).toBe(false, 'Next button is enabled on last page'); + expect(await pagination.getCurrentPage()).toContain('Page 5'); + expect(await pagination.isNextEnabled()).toBe(false, 'Next button is enabled on last page'); }); }); diff --git a/e2e/suites/pagination/pag-recent-files.test.ts b/e2e/suites/pagination/pag-recent-files.test.ts index cd09fad939..8154121696 100755 --- a/e2e/suites/pagination/pag-recent-files.test.ts +++ b/e2e/suites/pagination/pag-recent-files.test.ts @@ -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,12 +69,12 @@ describe('Pagination on multiple pages on Recent Files', () => { }); it('Pagination control default values - [C280104]', async () => { - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await pagination.maxItems.getText()).toContain('25'); - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.totalPages.getText()).toContain('of 5'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.getTotalPages()).toContain('of 5'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); }); it('Items per page values - [C280105]', async () => { @@ -90,24 +90,24 @@ describe('Pagination on multiple pages on Recent Files', () => { it('current page menu items - [C280106]', async () => { await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('25'); - expect(await pagination.getText(pagination.maxItems)).toContain('25'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 5'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getTotalPages()).toContain('of 5'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(5); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('50'); - expect(await pagination.getText(pagination.maxItems)).toContain('50'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 3'); + expect(await pagination.getMaxItems()).toContain('50'); + expect(await pagination.getTotalPages()).toContain('of 3'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(3); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('100'); - expect(await pagination.getText(pagination.maxItems)).toContain('100'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 2'); + expect(await pagination.getMaxItems()).toContain('100'); + expect(await pagination.getTotalPages()).toContain('of 2'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(2); await pagination.menu.closeMenu(); @@ -119,43 +119,43 @@ describe('Pagination on multiple pages on Recent Files', () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(3); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('51-75 of 101'); - expect(await pagination.currentPage.getText()).toContain('Page 3'); - expect(await pagination.previousButton.isEnabled()).toBe(true, 'Previous button is not enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); - expect(await dataTable.getRowByName('file-40').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('51-75 of 101'); + expect(await pagination.getCurrentPage()).toContain('Page 3'); + expect(await pagination.isPreviousEnabled()).toBe(true, 'Previous button is not enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + expect(await dataTable.isItemPresent('file-40')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); it('navigate to next and previous pages - [C280110]', async () => { - await pagination.nextButton.click(); + await pagination.clickNext(); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('26-50 of 101'); - expect(await dataTable.getRowByName('file-70').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('26-50 of 101'); + expect(await dataTable.isItemPresent('file-70')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(2); await dataTable.waitForHeader(); - await pagination.previousButton.click(); + await pagination.clickPrevious(); await dataTable.waitForHeader(); - expect(pagination.range.getText()).toContain('1-25 of 101'); - expect(dataTable.getRowByName('file-88').isPresent()).toBe(true, 'File not found on page'); + expect(pagination.getRange()).toContain('1-25 of 101'); + expect(dataTable.isItemPresent('file-88')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); it('Previous button is disabled on first page - [C280108]', async () => { - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled on first page'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled on first page'); }); it('Next button is disabled on last page - [C280109]', async () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(5); expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); - expect(await pagination.currentPage.getText()).toContain('Page 5'); - expect(await pagination.nextButton.isEnabled()).toBe(false, 'Next button is enabled on last page'); + expect(await pagination.getCurrentPage()).toContain('Page 5'); + expect(await pagination.isNextEnabled()).toBe(false, 'Next button is enabled on last page'); }); }); diff --git a/e2e/suites/pagination/pag-search-results.test.ts b/e2e/suites/pagination/pag-search-results.test.ts index b5e64e92ae..b6b21d6e3f 100755 --- a/e2e/suites/pagination/pag-search-results.test.ts +++ b/e2e/suites/pagination/pag-search-results.test.ts @@ -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 @@ -71,12 +71,12 @@ describe('Pagination on multiple pages on Search Results', () => { }); it('Pagination control default values - [C290125]', async () => { - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await pagination.maxItems.getText()).toContain('25'); - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.totalPages.getText()).toContain('of 5'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.getTotalPages()).toContain('of 5'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); }); it('Items per page values - [C290126]', async () => { @@ -92,24 +92,24 @@ describe('Pagination on multiple pages on Search Results', () => { it('current page menu items - [C290127]', async () => { await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('25'); - expect(await pagination.getText(pagination.maxItems)).toContain('25'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 5'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getTotalPages()).toContain('of 5'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(5); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('50'); - expect(await pagination.getText(pagination.maxItems)).toContain('50'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 3'); + expect(await pagination.getMaxItems()).toContain('50'); + expect(await pagination.getTotalPages()).toContain('of 3'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(3); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('100'); - expect(await pagination.getText(pagination.maxItems)).toContain('100'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 2'); + expect(await pagination.getMaxItems()).toContain('100'); + expect(await pagination.getTotalPages()).toContain('of 2'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(2); await pagination.menu.closeMenu(); @@ -121,40 +121,40 @@ describe('Pagination on multiple pages on Search Results', () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(3); await dataTable.waitForBody(); - expect(await pagination.range.getText()).toContain('51-75 of 101'); - expect(await pagination.currentPage.getText()).toContain('Page 3'); - expect(await pagination.previousButton.isEnabled()).toBe(true, 'Previous button is not enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); + expect(await pagination.getRange()).toContain('51-75 of 101'); + expect(await pagination.getCurrentPage()).toContain('Page 3'); + expect(await pagination.isPreviousEnabled()).toBe(true, 'Previous button is not enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); await pagination.resetToDefaultPageNumber(); }); it('navigate to next and previous pages - [C290131]', async () => { - await pagination.nextButton.click(); + await pagination.clickNext(); await dataTable.waitForBody(); - expect(await pagination.range.getText()).toContain('26-50 of 101'); + expect(await pagination.getRange()).toContain('26-50 of 101'); await pagination.resetToDefaultPageNumber(); await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(2); await dataTable.waitForBody(); - await pagination.previousButton.click(); + await pagination.clickPrevious(); await dataTable.waitForBody(); - expect(pagination.range.getText()).toContain('1-25 of 101'); + expect(pagination.getRange()).toContain('1-25 of 101'); await pagination.resetToDefaultPageNumber(); }); it('Previous button is disabled on first page - [C290129]', async () => { - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled on first page'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled on first page'); }); it('Next button is disabled on last page - [C290130]', async () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(5); expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); - expect(await pagination.currentPage.getText()).toContain('Page 5'); - expect(await pagination.nextButton.isEnabled()).toBe(false, 'Next button is enabled on last page'); + expect(await pagination.getCurrentPage()).toContain('Page 5'); + expect(await pagination.isNextEnabled()).toBe(false, 'Next button is enabled on last page'); }); }); diff --git a/e2e/suites/pagination/pag-shared-files.test.ts b/e2e/suites/pagination/pag-shared-files.test.ts index 7d4597590a..d3439a1b82 100755 --- a/e2e/suites/pagination/pag-shared-files.test.ts +++ b/e2e/suites/pagination/pag-shared-files.test.ts @@ -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 @@ -72,12 +72,12 @@ describe('Pagination on multiple pages on Shared Files', () => { }); it('Pagination control default values - [C280095]', async () => { - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await pagination.maxItems.getText()).toContain('25'); - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.totalPages.getText()).toContain('of 5'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.getTotalPages()).toContain('of 5'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); }); it('Items per page values - [C280096]', async () => { @@ -94,24 +94,24 @@ describe('Pagination on multiple pages on Shared Files', () => { it('current page menu items - [C280097]', async () => { await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('25'); - expect(await pagination.getText(pagination.maxItems)).toContain('25'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 5'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getTotalPages()).toContain('of 5'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(5); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('50'); - expect(await pagination.getText(pagination.maxItems)).toContain('50'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 3'); + expect(await pagination.getMaxItems()).toContain('50'); + expect(await pagination.getTotalPages()).toContain('of 3'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(3); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('100'); - expect(await pagination.getText(pagination.maxItems)).toContain('100'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 2'); + expect(await pagination.getMaxItems()).toContain('100'); + expect(await pagination.getTotalPages()).toContain('of 2'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(2); await pagination.menu.closeMenu(); @@ -123,43 +123,43 @@ describe('Pagination on multiple pages on Shared Files', () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(3); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('51-75 of 101'); - expect(await pagination.currentPage.getText()).toContain('Page 3'); - expect(await pagination.previousButton.isEnabled()).toBe(true, 'Previous button is not enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); - expect(await dataTable.getRowByName('file-40').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('51-75 of 101'); + expect(await pagination.getCurrentPage()).toContain('Page 3'); + expect(await pagination.isPreviousEnabled()).toBe(true, 'Previous button is not enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + expect(await dataTable.isItemPresent('file-40')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); it('navigate to next and previous pages - [C280101]', async () => { - await pagination.nextButton.click(); + await pagination.clickNext(); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('26-50 of 101'); - expect(await dataTable.getRowByName('file-70').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('26-50 of 101'); + expect(await dataTable.isItemPresent('file-70')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(2); await dataTable.waitForHeader(); - await pagination.previousButton.click(); + await pagination.clickPrevious(); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await dataTable.getRowByName('file-88').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await dataTable.isItemPresent('file-88')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); it('Previous button is disabled on first page - [C280099]', async () => { - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled on first page'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled on first page'); }); it('Next button is disabled on last page - [C280100]', async () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(5); expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); - expect(await pagination.currentPage.getText()).toContain('Page 5'); - expect(await pagination.nextButton.isEnabled()).toBe(false, 'Next button is enabled on last page'); + expect(await pagination.getCurrentPage()).toContain('Page 5'); + expect(await pagination.isNextEnabled()).toBe(false, 'Next button is enabled on last page'); }); }); diff --git a/e2e/suites/pagination/pag-single-page.test.ts b/e2e/suites/pagination/pag-single-page.test.ts index bffffc44a9..6c9560549e 100755 --- a/e2e/suites/pagination/pag-single-page.test.ts +++ b/e2e/suites/pagination/pag-single-page.test.ts @@ -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,32 +81,37 @@ describe('Pagination on single page', () => { it('page selector not displayed on Favorites - [C280112]', async () => { await page.clickFavoritesAndWait(); - expect(await pagination.pagesButton.isPresent()).toBe(false, 'page selector displayed'); + expect(await pagination.isPagesButtonPresent()).toBe(false, 'page selector displayed'); }); - it('page selector not displayed on File Libraries - [C280085]', async () => { - await page.clickFileLibrariesAndWait(); - expect(await pagination.pagesButton.isPresent()).toBe(false, 'page selector displayed'); + it('page selector not displayed on My Libraries - [C280085]', async () => { + await page.goToMyLibrariesAndWait(); + expect(await pagination.isPagesButtonPresent()).toBe(false, 'page selector displayed'); + }); + + it('page selector not displayed on Favorite Libraries - [C291874]', async () => { + await page.goToFavoriteLibrariesAndWait(); + expect(await pagination.isPagesButtonPresent()).toBe(false, 'page selector displayed'); }); it('page selector not displayed on Personal Files - [C280076]', async () => { await page.clickPersonalFilesAndWait(); - expect(await pagination.pagesButton.isPresent()).toBe(false, 'page selector displayed'); + expect(await pagination.isPagesButtonPresent()).toBe(false, 'page selector displayed'); }); it('page selector not displayed on Recent Files - [C280103]', async () => { await page.clickRecentFilesAndWait(); - expect(await pagination.pagesButton.isPresent()).toBe(false, 'page selector displayed'); + expect(await pagination.isPagesButtonPresent()).toBe(false, 'page selector displayed'); }); it('page selector not displayed on Shared Files - [C280094]', async () => { await page.clickSharedFilesAndWait(); - expect(await pagination.pagesButton.isPresent()).toBe(false, 'page selector displayed'); + expect(await pagination.isPagesButtonPresent()).toBe(false, 'page selector displayed'); }); it('page selector not displayed on Trash - [C280121]', async () => { await page.clickTrashAndWait(); - expect(await pagination.pagesButton.isPresent()).toBe(false, 'page selector displayed'); + expect(await pagination.isPagesButtonPresent()).toBe(false, 'page selector displayed'); }); it('page selector not displayed on Search results - [C290124]', async () => { @@ -114,7 +119,7 @@ describe('Pagination on single page', () => { await searchInput.checkOnlyFiles(); await searchInput.searchFor(file); await dataTable.waitForBody(); - expect(await pagination.pagesButton.isPresent()).toBe(false, 'page selector displayed'); + expect(await pagination.isPagesButtonPresent()).toBe(false, 'page selector displayed'); }); }); diff --git a/e2e/suites/pagination/pag-trash.test.ts b/e2e/suites/pagination/pag-trash.test.ts index 93abb03fba..30c0e863b5 100755 --- a/e2e/suites/pagination/pag-trash.test.ts +++ b/e2e/suites/pagination/pag-trash.test.ts @@ -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 @@ -68,12 +68,12 @@ describe('Pagination on multiple pages on Trash', () => { }); it('Pagination control default values - [C280122]', async () => { - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await pagination.maxItems.getText()).toContain('25'); - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.totalPages.getText()).toContain('of 5'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.getTotalPages()).toContain('of 5'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); }); it('Items per page values - [C280123]', async () => { @@ -89,24 +89,24 @@ describe('Pagination on multiple pages on Trash', () => { it('current page menu items - [C280124]', async () => { await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('25'); - expect(await pagination.getText(pagination.maxItems)).toContain('25'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 5'); + expect(await pagination.getMaxItems()).toContain('25'); + expect(await pagination.getTotalPages()).toContain('of 5'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(5); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('50'); - expect(await pagination.getText(pagination.maxItems)).toContain('50'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 3'); + expect(await pagination.getMaxItems()).toContain('50'); + expect(await pagination.getTotalPages()).toContain('of 3'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(3); await pagination.menu.closeMenu(); await pagination.openMaxItemsMenu(); await pagination.menu.clickMenuItem('100'); - expect(await pagination.getText(pagination.maxItems)).toContain('100'); - expect(await pagination.getText(pagination.totalPages)).toContain('of 2'); + expect(await pagination.getMaxItems()).toContain('100'); + expect(await pagination.getTotalPages()).toContain('of 2'); await pagination.openCurrentPageMenu(); expect(await pagination.menu.getItemsCount()).toBe(2); await pagination.menu.closeMenu(); @@ -118,43 +118,43 @@ describe('Pagination on multiple pages on Trash', () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(3); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('51-75 of 101'); - expect(await pagination.currentPage.getText()).toContain('Page 3'); - expect(await pagination.previousButton.isEnabled()).toBe(true, 'Previous button is not enabled'); - expect(await pagination.nextButton.isEnabled()).toBe(true, 'Next button is not enabled'); - expect(await dataTable.getRowByName('file-40').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('51-75 of 101'); + expect(await pagination.getCurrentPage()).toContain('Page 3'); + expect(await pagination.isPreviousEnabled()).toBe(true, 'Previous button is not enabled'); + expect(await pagination.isNextEnabled()).toBe(true, 'Next button is not enabled'); + expect(await dataTable.isItemPresent('file-40')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); it('navigate to next and previous pages - [C280128]', async () => { - await pagination.nextButton.click(); + await pagination.clickNext(); await dataTable.waitForHeader(); - expect(pagination.range.getText()).toContain('26-50 of 101'); - expect(dataTable.getRowByName('file-70').isPresent()).toBe(true, 'File not found on page'); + expect(pagination.getRange()).toContain('26-50 of 101'); + expect(dataTable.isItemPresent('file-70')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(2); await dataTable.waitForHeader(); - await pagination.previousButton.click(); + await pagination.clickPrevious(); await dataTable.waitForHeader(); - expect(await pagination.range.getText()).toContain('1-25 of 101'); - expect(await dataTable.getRowByName('file-88').isPresent()).toBe(true, 'File not found on page'); + expect(await pagination.getRange()).toContain('1-25 of 101'); + expect(await dataTable.isItemPresent('file-88')).toBe(true, 'File not found on page'); await pagination.resetToDefaultPageNumber(); }); it('Previous button is disabled on first page - [C280126]', async () => { - expect(await pagination.currentPage.getText()).toContain('Page 1'); - expect(await pagination.previousButton.isEnabled()).toBe(false, 'Previous button is enabled on first page'); + expect(await pagination.getCurrentPage()).toContain('Page 1'); + expect(await pagination.isPreviousEnabled()).toBe(false, 'Previous button is enabled on first page'); }); it('Next button is disabled on last page - [C280127]', async () => { await pagination.openCurrentPageMenu(); await pagination.menu.clickNthItem(5); expect(await dataTable.countRows()).toBe(1, 'Incorrect number of items on the last page'); - expect(await pagination.currentPage.getText()).toContain('Page 5'); - expect(await pagination.nextButton.isEnabled()).toBe(false, 'Next button is enabled on last page'); + expect(await pagination.getCurrentPage()).toContain('Page 5'); + expect(await pagination.isNextEnabled()).toBe(false, 'Next button is enabled on last page'); }); }); diff --git a/e2e/suites/search/search-input.test.ts b/e2e/suites/search/search-input.test.ts index 3dfb6e0644..ac57d4d983 100644 --- a/e2e/suites/search/search-input.test.ts +++ b/e2e/suites/search/search-input.test.ts @@ -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 @@ -24,8 +24,7 @@ */ import { BrowsingPage, LoginPage } from '../../pages/pages'; -// import { Utils } from '../../utilities/utils'; -import { browser } from 'protractor'; +import { Utils } from '../../utilities/utils'; describe('Search input', () => { const loginPage = new LoginPage(); @@ -38,8 +37,8 @@ describe('Search input', () => { }); beforeEach(async (done) => { - // await Utils.pressEscape(); - await browser.actions().mouseMove(browser.$('body'), { x: 0, y: 0 }).click().perform(); + await Utils.pressEscape(); + await page.clickPersonalFiles(); done(); }); diff --git a/e2e/suites/search/search-results-libraries.test.ts b/e2e/suites/search/search-results-libraries.test.ts index e54d49c88e..249da46152 100644 --- a/e2e/suites/search/search-results-libraries.test.ts +++ b/e2e/suites/search/search-results-libraries.test.ts @@ -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 @@ -102,7 +102,7 @@ describe('Search results - libraries', () => { await apis.admin.sites.createSite(adminPrivate, SITE_VISIBILITY.PRIVATE); await apis.user.sites.waitForApi({ expect: 12 }); - await apis.user.queries.waitForApi('lib', { expect: 2 }); + await apis.user.queries.waitForSites('lib', { expect: 2 }); await loginPage.loginWith(username); done(); @@ -127,10 +127,10 @@ describe('Search results - libraries', () => { await searchInput.searchFor(site1.name); await dataTable.waitForBody(); - expect(await dataTable.getRowByName(site1.name).isPresent()).toBe(true, `${site1.name} not displayed`); - expect(await dataTable.getRowByName(site2.name).isPresent()).toBe(false, `${site2.name} displayed`); - expect(await dataTable.getRowByName(site3.name).isPresent()).toBe(false, `${site3.name} displayed`); - expect(await dataTable.getRowByName(site4.name).isPresent()).toBe(false, `${site4.name} displayed`); + expect(await dataTable.isItemPresent(site1.name)).toBe(true, `${site1.name} not displayed`); + expect(await dataTable.isItemPresent(site2.name)).toBe(false, `${site2.name} displayed`); + expect(await dataTable.isItemPresent(site3.name)).toBe(false, `${site3.name} displayed`); + expect(await dataTable.isItemPresent(site4.name)).toBe(false, `${site4.name} displayed`); }); it('Search library - partial name match - [C290013]', async () => { @@ -139,10 +139,10 @@ describe('Search results - libraries', () => { await searchInput.searchFor('lib'); await dataTable.waitForBody(); - expect(await dataTable.getRowByName(site1.name).isPresent()).toBe(true, `${site1.name} not displayed`); - expect(await dataTable.getRowByName(site2.name).isPresent()).toBe(false, `${site2.name} displayed`); - expect(await dataTable.getRowByName(site3.name).isPresent()).toBe(true, `${site3.name} not displayed`); - expect(await dataTable.getRowByName(site4.name).isPresent()).toBe(false, `${site4.name} displayed`); + expect(await dataTable.isItemPresent(site1.name)).toBe(true, `${site1.name} not displayed`); + expect(await dataTable.isItemPresent(site2.name)).toBe(false, `${site2.name} displayed`); + expect(await dataTable.isItemPresent(site3.name)).toBe(true, `${site3.name} not displayed`); + expect(await dataTable.isItemPresent(site4.name)).toBe(false, `${site4.name} displayed`); }); it('Search library - description match - [C290014]', async () => { @@ -151,10 +151,10 @@ describe('Search results - libraries', () => { await searchInput.searchFor(site4.description); await dataTable.waitForBody(); - expect(await dataTable.getRowByName(site1.name).isPresent()).toBe(false, `${site1.name} displayed`); - expect(await dataTable.getRowByName(site2.name).isPresent()).toBe(false, `${site2.name} displayed`); - expect(await dataTable.getRowByName(site3.name).isPresent()).toBe(false, `${site3.name} displayed`); - expect(await dataTable.getRowByName(site4.name).isPresent()).toBe(true, `${site4.name} not displayed`); + expect(await dataTable.isItemPresent(site1.name)).toBe(false, `${site1.name} displayed`); + expect(await dataTable.isItemPresent(site2.name)).toBe(false, `${site2.name} displayed`); + expect(await dataTable.isItemPresent(site3.name)).toBe(false, `${site3.name} displayed`); + expect(await dataTable.isItemPresent(site4.name)).toBe(true, `${site4.name} not displayed`); }); it('Results page title - [C290015]', async () => { @@ -172,14 +172,10 @@ describe('Search results - libraries', () => { await searchInput.searchFor(site1.name); await dataTable.waitForBody(); - const labels = [ 'Name', 'My Role', 'Visibility' ]; - const elements = labels.map(label => dataTable.getColumnHeaderByLabel(label)); + const expectedColumns = [ 'Thumbnail', 'Name', 'My Role', 'Visibility' ]; + const actualColumns = await dataTable.getColumnHeadersText(); - expect(await dataTable.getColumnHeaders().count()).toBe(3 + 1, 'Incorrect number of columns'); - - await elements.forEach(async (element, index) => { - expect(await element.isPresent()).toBe(true, `"${labels[index]}" is missing`); - }); + expect(actualColumns).toEqual(expectedColumns); }); it('Library visibility is correctly displayed - [C290017]', async () => { @@ -194,17 +190,11 @@ describe('Search results - libraries', () => { [userSitePublic]: SITE_VISIBILITY.PUBLIC }; - const rowCells = await dataTable.getRows().map((row) => { - return row.all(dataTable.cell).map(async cell => await cell.getText()); - }); - const sitesList = rowCells.reduce((acc, cell) => { - acc[cell[1]] = cell[3].toUpperCase(); - return acc; - }, {}); - - Object.keys(expectedSitesVisibility).forEach((expectedSite) => { - expect(sitesList[expectedSite]).toEqual(expectedSitesVisibility[expectedSite]); - }); + const sitesList = await dataTable.getSitesNameAndVisibility(); + + for (const site of Object.keys(expectedSitesVisibility)) { + expect(sitesList[site]).toEqual(expectedSitesVisibility[site]); + } }); it('User role is correctly displayed - [C290018]', async () => { @@ -220,17 +210,11 @@ describe('Search results - libraries', () => { [adminSite4]: SITE_ROLES.SITE_MANAGER.LABEL }; - const rowCells = await dataTable.getRows().map((row) => { - return row.all(dataTable.cell).map(async cell => await cell.getText()); - }); - const sitesList = rowCells.reduce((acc, cell) => { - acc[cell[1]] = cell[2]; - return acc; - }, {}); - - Object.keys(expectedSitesRoles).forEach((expectedSite) => { - expect(sitesList[expectedSite]).toEqual(expectedSitesRoles[expectedSite]); - }); + const sitesList = await dataTable.getSitesNameAndRole(); + + for (const site of Object.keys(expectedSitesRoles)) { + expect(sitesList[site]).toEqual(expectedSitesRoles[site]); + } }); it('Private sites are not displayed when user is not a member - [C290019]', async () => { @@ -239,7 +223,7 @@ describe('Search results - libraries', () => { await searchInput.searchFor('admin-site'); await dataTable.waitForBody(); - expect(await dataTable.getRowByName(adminPrivate).isPresent()).toBe(false, `${adminPrivate} is displayed`); + expect(await dataTable.isItemPresent(adminPrivate)).toBe(false, `${adminPrivate} is displayed`); }); it('Search libraries with special characters - [C290028]', async () => { @@ -248,7 +232,7 @@ describe('Search results - libraries', () => { await searchInput.searchFor(siteRussian.name); await dataTable.waitForBody(); - expect(await dataTable.getRowByName(siteRussian.name).isPresent()).toBe(true, `${siteRussian.name} not displayed`); + expect(await dataTable.isItemPresent(siteRussian.name)).toBe(true, `${siteRussian.name} not displayed`); }); }); diff --git a/e2e/suites/search/search-results.test.ts b/e2e/suites/search/search-results.test.ts index bae09fb1b5..9c9d26df95 100644 --- a/e2e/suites/search/search-results.test.ts +++ b/e2e/suites/search/search-results.test.ts @@ -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 @@ -52,7 +52,7 @@ describe('Search results', () => { await apis.user.sites.createSite(site); await apis.user.search.waitForApi(username, { expect: 1 }); - await apis.user.queries.waitForApi(site, { expect: 1 }); + await apis.user.queries.waitForSites(site, { expect: 1 }); await loginPage.loginWith(username); done(); @@ -78,42 +78,42 @@ describe('Search results', () => { await searchInput.searchFor('test'); await dataTable.waitForBody(); - expect(await dataTable.getRowByName(file).isPresent()).toBe(true, `${file} not displayed`); - expect(await dataTable.getRowByName(folder).isPresent()).toBe(false, `${folder} is displayed`); - expect(await dataTable.getRowByName(site).isPresent()).toBe(false, `${site} is displayed`); + expect(await dataTable.isItemPresent(file)).toBe(true, `${file} not displayed`); + expect(await dataTable.isItemPresent(folder)).toBe(false, `${folder} is displayed`); + expect(await dataTable.isItemPresent(site)).toBe(false, `${site} is displayed`); }); it('Only folders are returned when Folders option is the only one checked - [C290006]', async () => { await searchInput.clickSearchButton(); await searchInput.checkOnlyFolders(); await searchInput.searchFor('test'); - await dataTable.waitForBody(); + await page.waitForResults(); - expect(await dataTable.getRowByName(file).isPresent()).toBe(false, `${file} is displayed`); - expect(await dataTable.getRowByName(folder).isPresent()).toBe(true, `${folder} not displayed`); - expect(await dataTable.getRowByName(site).isPresent()).toBe(false, `${site} is displayed`); + expect(await dataTable.isItemPresent(file)).toBe(false, `${file} is displayed`); + expect(await dataTable.isItemPresent(folder)).toBe(true, `${folder} not displayed`); + expect(await dataTable.isItemPresent(site)).toBe(false, `${site} is displayed`); }); it('Files and folders are returned when both Files and Folders options are checked - [C290007]', async () => { await searchInput.clickSearchButton(); await searchInput.checkFilesAndFolders(); await searchInput.searchFor('test'); - await dataTable.waitForBody(); + await page.waitForResults(); - expect(await dataTable.getRowByName(file).isPresent()).toBe(true, `${file} not displayed`); - expect(await dataTable.getRowByName(folder).isPresent()).toBe(true, `${folder} not displayed`); - expect(await dataTable.getRowByName(site).isPresent()).toBe(false, `${site} is displayed`); + expect(await dataTable.isItemPresent(file)).toBe(true, `${file} not displayed`); + expect(await dataTable.isItemPresent(folder)).toBe(true, `${folder} not displayed`); + expect(await dataTable.isItemPresent(site)).toBe(false, `${site} is displayed`); }); it('Only libraries are returned when Libraries option is checked - [C290008]', async () => { await searchInput.clickSearchButton(); await searchInput.checkLibraries(); await searchInput.searchFor('test'); - await dataTable.waitForBody(); + await page.waitForResults(); - expect(await dataTable.getRowByName(file).isPresent()).toBe(false, `${file} is displayed`); - expect(await dataTable.getRowByName(folder).isPresent()).toBe(false, `${folder} is displayed`); - expect(await dataTable.getRowByName(site).isPresent()).toBe(true, `${site} not displayed`); + expect(await dataTable.isItemPresent(file)).toBe(false, `${file} is displayed`); + expect(await dataTable.isItemPresent(folder)).toBe(false, `${folder} is displayed`); + expect(await dataTable.isItemPresent(site)).toBe(true, `${site} not displayed`); }); }); diff --git a/e2e/suites/viewer/viewer-actions.test.ts b/e2e/suites/viewer/viewer-actions.test.ts index 1274f8653b..6228f0ff47 100755 --- a/e2e/suites/viewer/viewer-actions.test.ts +++ b/e2e/suites/viewer/viewer-actions.test.ts @@ -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 @@ -31,11 +31,13 @@ import { Viewer } from '../../components/viewer/viewer'; import { CopyMoveDialog } from './../../components/dialog/copy-move-dialog'; import { ShareDialog } from './../../components/dialog/share-dialog'; import { ManageVersionsDialog } from './../../components/dialog/manage-versions-dialog'; +import { UploadNewVersionDialog } from './../../components/dialog/upload-new-version-dialog'; describe('Viewer actions', () => { const username = `user-${Utils.random()}`; const docxFile = FILES.docxFile; + const docxFile2 = FILES.docxFile2; const xlsxFileForMove = FILES.xlsxFile; const pdfFileForDelete = FILES.pdfFile; @@ -52,29 +54,45 @@ describe('Viewer actions', () => { const copyMoveDialog = new CopyMoveDialog(); const shareDialog = new ShareDialog(); const manageVersionsDialog = new ManageVersionsDialog(); + const uploadNewVersionDialog = new UploadNewVersionDialog(); beforeAll(async done => { await apis.admin.people.createUser({ username }); done(); }); - xit(''); - - describe('on Personal Files', () => { + describe('from Personal Files', () => { const parent = `parentPF-${Utils.random()}`; let parentId; const destination = `destPF-${Utils.random()}`; let destinationId; const docxPersonalFiles = `docxPF-${Utils.random()}.docx`; let docxFileId; + const docxLockedPersonalFiles = `docxLockedPF-${Utils.random()}.docx`; let docxLockedId; const xlsxPersonalFiles = `xlsxPF-${Utils.random()}.xlsx`; const pdfPersonalFiles = `pdfPF-${Utils.random()}.pdf`; + const filePersonalFiles = docxFile2; let filePersonalFilesId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { parentId = (await apis.user.nodes.createFolder(parent)).entry.id; destinationId = (await apis.user.nodes.createFolder(destination)).entry.id; + docxFileId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxPersonalFiles)).entry.id; + docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxLockedPersonalFiles)).entry.id; + filePersonalFilesId = (await apis.user.upload.uploadFile(docxFile2, parentId)).entry.id; await apis.user.upload.uploadFileWithRename(xlsxFileForMove, parentId, xlsxPersonalFiles); await apis.user.upload.uploadFileWithRename(pdfFileForDelete, parentId, pdfPersonalFiles); + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForUploadNewVersion)).entry.id; + + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); + await apis.user.nodes.lockFile(docxLockedId); + await loginPage.loginWith(username); done(); }); @@ -100,103 +118,167 @@ describe('Viewer actions', () => { it('Correct actions appear in the viewer toolbar - [C282025]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); - expect(await toolbar.isButtonPresent('View')).toBe(false, `View is displayed`); - expect(await toolbar.isButtonPresent('Download')).toBe(true, `Download is not displayed`); - expect(await toolbar.isButtonPresent('Print')).toBe(true, `Print is not displayed`); - expect(await toolbar.isButtonPresent('Activate full-screen mode')).toBe(true, `Full screen is not displayed`); - expect(await toolbar.isShareButtonPresent()).toBe(true, `Share is not displayed`); - expect(await toolbar.isButtonPresent('View details')).toBe(true, `view details is not displayed`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + await toolbar.openMoreMenu(); - expect(await toolbar.menu.isMenuItemPresent('Favorite')).toBe(true, `Favorite is not displayed`); - expect(await toolbar.menu.isMenuItemPresent('Copy')).toBe(true, `Copy is not displayed`); - expect(await toolbar.menu.isMenuItemPresent('Move')).toBe(true, `Move is not displayed`); - expect(await toolbar.menu.isMenuItemPresent('Delete')).toBe(true, `Delete is not displayed`); - expect(await toolbar.menu.isMenuItemPresent('Manage Versions')).toBe(true, `Manage versions is not displayed`); - expect(await toolbar.menu.isMenuItemPresent('Permissions')).toBe(true, `Permissions is not displayed`); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('Correct actions appear in the viewer toolbar for a locked file - [C297583]', async () => { + await dataTable.doubleClickOnRowByName(docxLockedPersonalFiles); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + await toolbar.closeMoreMenu(); }); it('Download action - [C268129]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); + + await toolbar.clickDownload(); - await toolbar.clickButton('Download'); expect(await Utils.fileExistsOnOS(docxPersonalFiles)).toBe(true, 'File not found in download location'); }); - it('Copy action - [C268130]', async (done) => { + it('Copy action - [C268130]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Copy'); + await toolbar.clickMoreActionsCopy(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickCopy(); expect(await page.getSnackBarMessage()).toContain('Copied 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(docxPersonalFiles).isPresent()).toBe(true, 'Item is not in the list'); + expect(await dataTable.isItemPresent(docxPersonalFiles)).toBe(true, 'Item is not in the list'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(docxPersonalFiles).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(docxPersonalFiles)).toBe(true, 'Item is not present in destination'); await apis.user.nodes.deleteNodeChildren(destinationId); - done(); }); it('Move action - [C268131]', async () => { await dataTable.doubleClickOnRowByName(xlsxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Move'); + await toolbar.clickMoreActionsMove(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickMove(); expect(await page.getSnackBarMessage()).toContain('Moved 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(xlsxPersonalFiles).isPresent()).toBe(false, 'Item was not moved'); + expect(await dataTable.isItemPresent(xlsxPersonalFiles)).toBe(false, 'Item was not moved'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(xlsxPersonalFiles).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(xlsxPersonalFiles)).toBe(true, 'Item is not present in destination'); }); it('Favorite action - [C268132]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); + await toolbar.clickMoreActionsFavorite(); await viewer.clickClose(); await page.clickFavoritesAndWait(); expect(await apis.user.favorites.isFavorite(docxFileId)).toBe(true, 'Item is not favorite'); - expect(await dataTable.getRowByName(docxPersonalFiles).isPresent()).toBe(true, 'Item is not present in Favorites list'); + expect(await dataTable.isItemPresent(docxPersonalFiles)).toBe(true, 'Item is not present in Favorites list'); }); it('Delete action - [C268133]', async () => { await dataTable.doubleClickOnRowByName(pdfPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); expect(await page.getSnackBarMessage()).toContain(`${pdfPersonalFiles} deleted`); expect(await viewer.isViewerOpened()).toBe(false, 'Viewer is opened'); await Utils.pressEscape(); await page.clickTrashAndWait(); - expect(await dataTable.getRowByName(pdfPersonalFiles).isPresent()).toBe(true, 'Item is not present in Trash'); + expect(await dataTable.isItemPresent(pdfPersonalFiles)).toBe(true, 'Item is not present in Trash'); + }); + + it('Edit Offline action - [C297584]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297585]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297586]', async () => { + await dataTable.doubleClickOnRowByName(filePersonalFiles); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(filePersonalFilesId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(filePersonalFilesId)).toEqual('2.0', 'File has incorrect version label'); }); it('Full screen action - [C279282]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); await Utils.getBrowserLog(); - await toolbar.clickButton('Activate full-screen mode'); + await toolbar.clickFullScreen(); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is closed after pressing Full screen'); const browserLogAfter = await Utils.getBrowserLog(); @@ -205,29 +287,28 @@ describe('Viewer actions', () => { it('Share action - [C286313]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); - await toolbar.clickShareButton(); + await toolbar.clickShare(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await shareDialog.clickClose(); }); it('Manage Versions action - [C286316]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Manage Versions'); + await toolbar.clickMoreActionsManageVersions(); expect(await manageVersionsDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await manageVersionsDialog.clickClose(); }); - // TODO: enable this once bug is fixed + // TODO: disabled until ACA-2176 is done xit('Pressing ESC in the viewer closes only the action dialog - [C286314]', async () => { await dataTable.doubleClickOnRowByName(docxPersonalFiles); - expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); + await viewer.waitForViewerToOpen(); - await toolbar.clickShareButton(); + await toolbar.clickShare(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await Utils.pressEscape(); expect(await shareDialog.isDialogOpen()).toBe(false, 'Dialog is still open'); @@ -235,28 +316,44 @@ describe('Viewer actions', () => { }); }); - describe('on File Libraries', () => { + describe('from File Libraries', () => { const siteName = `site-${Utils.random()}`; const destination = `destFL-${Utils.random()}`; let destinationId; const docxLibraries = `docxFL-${Utils.random()}.docx`; let docxFileId; + const docxLockedLibraries = `docxLockedFL-${Utils.random()}.docx`; let docxLockedId; const xlsxLibraries = `xlsxFL-${Utils.random()}.xlsx`; const pdfLibraries = `pdfFL-${Utils.random()}.pdf`; + const fileLibraries = docxFile2; let fileLibrariesId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { await apis.user.sites.createSite(siteName); const docLibId = await apis.user.sites.getDocLibId(siteName); destinationId = (await apis.user.nodes.createFolder(destination)).entry.id; docxFileId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, docxLibraries)).entry.id; + docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, docxLockedLibraries)).entry.id; + fileLibrariesId = (await apis.user.upload.uploadFile(docxFile2, docLibId)).entry.id; + await apis.user.nodes.lockFile(docxLockedId); await apis.user.upload.uploadFileWithRename(xlsxFileForMove, docLibId, xlsxLibraries); await apis.user.upload.uploadFileWithRename(pdfFileForDelete, docLibId, pdfLibraries); + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, docLibId, fileForUploadNewVersion)).entry.id; + + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); + await loginPage.loginWith(username); done(); }); beforeEach(async (done) => { - await page.clickFileLibrariesAndWait(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteName); await dataTable.waitForHeader(); done(); @@ -274,11 +371,63 @@ describe('Viewer actions', () => { done(); }); + it('Correct actions appear in the viewer toolbar - [C297587]', async () => { + await dataTable.doubleClickOnRowByName(docxLibraries); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('Correct actions appear in the viewer toolbar for a locked file - [C297588]', async () => { + await dataTable.doubleClickOnRowByName(docxLockedLibraries); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + it('Download action - [C286369]', async () => { await dataTable.doubleClickOnRowByName(docxLibraries); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.clickButton('Download'); + await toolbar.clickDownload(); expect(await Utils.fileExistsOnOS(docxLibraries)).toBe(true, 'File not found in download location'); }); @@ -286,18 +435,17 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(docxLibraries); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Copy'); + await toolbar.clickMoreActionsCopy(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickCopy(); expect(await page.getSnackBarMessage()).toContain('Copied 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(docxLibraries).isPresent()).toBe(true, 'Item is not in the list'); + expect(await dataTable.isItemPresent(docxLibraries)).toBe(true, 'Item is not in the list'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(docxLibraries).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(docxLibraries)).toBe(true, 'Item is not present in destination'); await apis.user.nodes.deleteNodeChildren(destinationId); done(); @@ -307,50 +455,84 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(xlsxLibraries); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Move'); + await toolbar.clickMoreActionsMove(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickMove(); expect(await page.getSnackBarMessage()).toContain('Moved 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(xlsxLibraries).isPresent()).toBe(false, 'Item was not moved'); + expect(await dataTable.isItemPresent(xlsxLibraries)).toBe(false, 'Item was not moved'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(xlsxLibraries).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(xlsxLibraries)).toBe(true, 'Item is not present in destination'); }); it('Favorite action - [C286372]', async () => { await dataTable.doubleClickOnRowByName(docxLibraries); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); + await toolbar.clickMoreActionsFavorite(); await viewer.clickClose(); await page.clickFavoritesAndWait(); expect(await apis.user.favorites.isFavorite(docxFileId)).toBe(true, `${docxLibraries} is not favorite`); - expect(await dataTable.getRowByName(docxLibraries).isPresent()).toBe(true, `${docxLibraries} is not present in Favorites list`); + expect(await dataTable.isItemPresent(docxLibraries)).toBe(true, `${docxLibraries} is not present in Favorites list`); }); it('Delete action - [C286373]', async () => { await dataTable.doubleClickOnRowByName(pdfLibraries); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); expect(await page.getSnackBarMessage()).toContain(`${pdfLibraries} deleted`); expect(await viewer.isViewerOpened()).toBe(false, 'Viewer is opened'); await Utils.pressEscape(); await page.clickTrashAndWait(); - expect(await dataTable.getRowByName(pdfLibraries).isPresent()).toBe(true, 'Item is not present in Trash'); + expect(await dataTable.isItemPresent(pdfLibraries)).toBe(true, 'Item is not present in Trash'); + }); + + it('Edit Offline action - [C297589]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297590]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297591]', async () => { + await dataTable.doubleClickOnRowByName(fileLibraries); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(fileLibrariesId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileLibrariesId)).toEqual('2.0', 'File has incorrect version label'); }); it('Share action - [C286374]', async () => { await dataTable.doubleClickOnRowByName(docxLibraries); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.clickShareButton(); + await toolbar.clickShare(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await shareDialog.clickClose(); }); @@ -359,30 +541,46 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(docxLibraries); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Manage Versions'); + await toolbar.clickMoreActionsManageVersions(); expect(await manageVersionsDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await manageVersionsDialog.clickClose(); }); }); - describe('on Recent Files', () => { + describe('from Recent Files', () => { const parent = `parentRF-${Utils.random()}`; let parentId; const destination = `destRF-${Utils.random()}`; let destinationId; const docxRecentFiles = `docxRF-${Utils.random()}.docx`; let docxFileId; + const docxLockedRecentFiles = `docxLockedRF-${Utils.random()}.docx`; let docxLockedId; const xlsxRecentFiles = `xlsxRF-${Utils.random()}.xlsx`; const pdfRecentFiles = `pdfRF-${Utils.random()}.pdf`; + const fileRecent = docxFile2; let fileRecentId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { await apis.user.search.waitForApi(username, {expect: 0}); parentId = (await apis.user.nodes.createFolder(parent)).entry.id; destinationId = (await apis.user.nodes.createFolder(destination)).entry.id; docxFileId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxRecentFiles)).entry.id; + docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxLockedRecentFiles)).entry.id; + fileRecentId = (await apis.user.upload.uploadFile(docxFile2, parentId)).entry.id; + + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForUploadNewVersion)).entry.id; + + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); + + await apis.user.nodes.lockFile(docxLockedId); await apis.user.upload.uploadFileWithRename(xlsxFileForMove, parentId, xlsxRecentFiles); await apis.user.upload.uploadFileWithRename(pdfFileForDelete, parentId, pdfRecentFiles); - await apis.user.search.waitForApi(username, {expect: 3}); + await apis.user.search.waitForApi(username, {expect: 8}); await loginPage.loginWith(username); done(); @@ -405,11 +603,63 @@ describe('Viewer actions', () => { done(); }); + it('Correct actions appear in the viewer toolbar - [C297592]', async () => { + await dataTable.doubleClickOnRowByName(docxRecentFiles); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isToggleFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('Correct actions appear in the viewer toolbar for a locked file - [C297593]', async () => { + await dataTable.doubleClickOnRowByName(docxLockedRecentFiles); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await toolbar.menu.isToggleFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + it('Download action - [C286383]', async () => { await dataTable.doubleClickOnRowByName(docxRecentFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.clickButton('Download'); + await toolbar.clickDownload(); expect(await Utils.fileExistsOnOS(docxRecentFiles)).toBe(true, 'File not found in download location'); }); @@ -417,18 +667,17 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(docxRecentFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Copy'); + await toolbar.clickMoreActionsCopy(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickCopy(); expect(await page.getSnackBarMessage()).toContain('Copied 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(docxRecentFiles).isPresent()).toBe(true, 'Item is not in the list'); + expect(await dataTable.isItemPresent(docxRecentFiles)).toBe(true, 'Item is not in the list'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(docxRecentFiles).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(docxRecentFiles)).toBe(true, 'Item is not present in destination'); await apis.user.nodes.deleteNodeChildren(destinationId); done(); @@ -438,51 +687,85 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(xlsxRecentFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Move'); + await toolbar.clickMoreActionsMove(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickMove(); expect(await page.getSnackBarMessage()).toContain('Moved 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(xlsxRecentFiles).isPresent()).toBe(true, 'Item is not in the list'); - expect(await dataTable.getItemLocationTileAttr(xlsxRecentFiles)).toContain(destination, 'Item was not moved'); + expect(await dataTable.isItemPresent(xlsxRecentFiles)).toBe(true, 'Item is not in the list'); + expect(await dataTable.getItemLocationTooltip(xlsxRecentFiles)).toContain(destination, 'Item was not moved'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(xlsxRecentFiles).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(xlsxRecentFiles)).toBe(true, 'Item is not present in destination'); }); it('Favorite action - [C286386]', async () => { await dataTable.doubleClickOnRowByName(docxRecentFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); + await toolbar.clickMoreActionsFavorite(); await viewer.clickClose(); await page.clickFavoritesAndWait(); expect(await apis.user.favorites.isFavorite(docxFileId)).toBe(true, 'Item is not favorite'); - expect(await dataTable.getRowByName(docxRecentFiles).isPresent()).toBe(true, 'Item is not present in Favorites list'); + expect(await dataTable.isItemPresent(docxRecentFiles)).toBe(true, 'Item is not present in Favorites list'); }); it('Delete action - [C286387]', async () => { await dataTable.doubleClickOnRowByName(pdfRecentFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); expect(await page.getSnackBarMessage()).toContain(`${pdfRecentFiles} deleted`); expect(await viewer.isViewerOpened()).toBe(false, 'Viewer is opened'); await Utils.pressEscape(); await page.clickTrashAndWait(); - expect(await dataTable.getRowByName(pdfRecentFiles).isPresent()).toBe(true, 'Item is not present in Trash'); + expect(await dataTable.isItemPresent(pdfRecentFiles)).toBe(true, 'Item is not present in Trash'); + }); + + it('Edit Offline action - [C297594]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297595]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297596]', async () => { + await dataTable.doubleClickOnRowByName(fileRecent); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(fileRecentId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileRecentId)).toEqual('2.0', 'File has incorrect version label'); }); it('Share action - [C286388]', async () => { await dataTable.doubleClickOnRowByName(docxRecentFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.clickShareButton(); + await toolbar.clickShare(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await shareDialog.clickClose(); }); @@ -491,30 +774,45 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(docxRecentFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Manage Versions'); + await toolbar.clickMoreActionsManageVersions(); expect(await manageVersionsDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await manageVersionsDialog.clickClose(); }); }); - describe('on Shared Files', () => { + describe('from Shared Files', () => { const parent = `parentSF-${Utils.random()}`; let parentId; const destination = `destSF-${Utils.random()}`; let destinationId; const docxSharedFiles = `docxSF-${Utils.random()}.docx`; let docxFileId; + const docxLockedSharedFiles = `docxLockedSF-${Utils.random()}.docx`; let docxLockedId; const xlsxSharedFiles = `xlsxSF-${Utils.random()}.xlsx`; let xlsxFileId; const pdfSharedFiles = `pdfSF-${Utils.random()}.pdf`; let pdfFileId; + const fileShared = docxFile2; let fileSharedId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { parentId = (await apis.user.nodes.createFolder(parent)).entry.id; destinationId = (await apis.user.nodes.createFolder(destination)).entry.id; docxFileId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxSharedFiles)).entry.id; + docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxLockedSharedFiles)).entry.id; xlsxFileId = (await apis.user.upload.uploadFileWithRename(xlsxFileForMove, parentId, xlsxSharedFiles)).entry.id; pdfFileId = (await apis.user.upload.uploadFileWithRename(pdfFileForDelete, parentId, pdfSharedFiles)).entry.id; + fileSharedId = (await apis.user.upload.uploadFile(docxFile2, parentId)).entry.id; + + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForUploadNewVersion)).entry.id; - await apis.user.shared.shareFilesByIds([docxFileId, xlsxFileId, pdfFileId]) - await apis.user.shared.waitForApi({expect: 3}); + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); + await apis.user.nodes.lockFile(docxLockedId); + + await apis.user.shared.shareFilesByIds([docxFileId, docxLockedId, xlsxFileId, pdfFileId, fileForCancelEditingId, fileForEditOfflineId, fileForUploadNewVersionId, fileSharedId]) + await apis.user.shared.waitForApi({expect: 8}); await loginPage.loginWith(username); done(); @@ -537,11 +835,63 @@ describe('Viewer actions', () => { done(); }); + it('Correct actions appear in the viewer toolbar - [C297597]', async () => { + await dataTable.doubleClickOnRowByName(docxSharedFiles); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('Correct actions appear in the viewer toolbar for a locked file - [C297598]', async () => { + await dataTable.doubleClickOnRowByName(docxLockedSharedFiles); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharedLinkSettingsPresent()).toBe(true, `Shared link settings is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await toolbar.menu.isFavoritePresent()).toBe(true, `Favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + it('Download action - [C286376]', async () => { await dataTable.doubleClickOnRowByName(docxSharedFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.clickButton('Download'); + await toolbar.clickDownload(); expect(await Utils.fileExistsOnOS(docxSharedFiles)).toBe(true, 'File not found in download location'); }); @@ -549,18 +899,17 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(docxSharedFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Copy'); + await toolbar.clickMoreActionsCopy(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickCopy(); expect(await page.getSnackBarMessage()).toContain('Copied 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(docxSharedFiles).isPresent()).toBe(true, 'Item is not in the list'); + expect(await dataTable.isItemPresent(docxSharedFiles)).toBe(true, 'Item is not in the list'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(docxSharedFiles).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(docxSharedFiles)).toBe(true, 'Item is not present in destination'); await apis.user.nodes.deleteNodeChildren(destinationId); done(); @@ -570,51 +919,85 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(xlsxSharedFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Move'); + await toolbar.clickMoreActionsMove(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickMove(); expect(await page.getSnackBarMessage()).toContain('Moved 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(xlsxSharedFiles).isPresent()).toBe(true, 'Item is not in the list'); - expect(await dataTable.getItemLocationTileAttr(xlsxSharedFiles)).toContain(destination, 'Item was not moved'); + expect(await dataTable.isItemPresent(xlsxSharedFiles)).toBe(true, 'Item is not in the list'); + expect(await dataTable.getItemLocationTooltip(xlsxSharedFiles)).toContain(destination, 'Item was not moved'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(xlsxSharedFiles).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(xlsxSharedFiles)).toBe(true, 'Item is not present in destination'); }); it('Favorite action - [C286379]', async () => { await dataTable.doubleClickOnRowByName(docxSharedFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); + await toolbar.clickMoreActionsFavorite(); await viewer.clickClose(); await page.clickFavoritesAndWait(); expect(await apis.user.favorites.isFavorite(docxFileId)).toBe(true, 'Item is not favorite'); - expect(await dataTable.getRowByName(docxSharedFiles).isPresent()).toBe(true, 'Item is not present in Favorites list'); + expect(await dataTable.isItemPresent(docxSharedFiles)).toBe(true, 'Item is not present in Favorites list'); }); it('Delete action - [C286380]', async () => { await dataTable.doubleClickOnRowByName(pdfSharedFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); expect(await page.getSnackBarMessage()).toContain(`${pdfSharedFiles} deleted`); expect(await viewer.isViewerOpened()).toBe(false, 'Viewer is opened'); await Utils.pressEscape(); await page.clickTrashAndWait(); - expect(await dataTable.getRowByName(pdfSharedFiles).isPresent()).toBe(true, 'Item is not present in Trash'); + expect(await dataTable.isItemPresent(pdfSharedFiles)).toBe(true, 'Item is not present in Trash'); + }); + + it('Edit Offline action - [C297601]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297602]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297603]', async () => { + await dataTable.doubleClickOnRowByName(fileShared); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(fileSharedId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileSharedId)).toEqual('2.0', 'File has incorrect version label'); }); it('Share action - [C286381]', async () => { await dataTable.doubleClickOnRowByName(docxSharedFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.clickShareEditButton(); + await toolbar.clickSharedLinkSettings(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await shareDialog.clickClose(); }); @@ -623,32 +1006,47 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(docxSharedFiles); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Manage Versions'); + await toolbar.clickMoreActionsManageVersions(); expect(await manageVersionsDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await manageVersionsDialog.clickClose(); }); }); - describe('on Favorites', () => { + describe('from Favorites', () => { const parent = `parentFav-${Utils.random()}`; let parentId; const destination = `destFav-${Utils.random()}`; let destinationId; const docxFavorites = `docxFav-${Utils.random()}.docx`; let docxFileId; + const docxLockedFavorites = `docxLockedFav-${Utils.random()}.docx`; let docxLockedId; const xlsxFavorites = `xlsxFav-${Utils.random()}.xlsx`; let xlsxFileId; const pdfFavorites = `pdfFav-${Utils.random()}.pdf`; let pdfFileId; + const fileFav = docxFile2; let fileFavId; + + const fileForEditOffline = `file1-${Utils.random()}.docx`; let fileForEditOfflineId; + const fileForCancelEditing = `file2-${Utils.random()}.docx`; let fileForCancelEditingId; + const fileForUploadNewVersion = `file3-${Utils.random()}.docx`; let fileForUploadNewVersionId; beforeAll(async (done) => { parentId = (await apis.user.nodes.createFolder(parent)).entry.id; destinationId = (await apis.user.nodes.createFolder(destination)).entry.id; docxFileId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxFavorites)).entry.id; + docxLockedId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, docxLockedFavorites)).entry.id; xlsxFileId = (await apis.user.upload.uploadFileWithRename(xlsxFileForMove, parentId, xlsxFavorites)).entry.id; pdfFileId = (await apis.user.upload.uploadFileWithRename(pdfFileForDelete, parentId, pdfFavorites)).entry.id; + fileFavId = (await apis.user.upload.uploadFile(docxFile2, parentId)).entry.id; + + fileForEditOfflineId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForEditOffline)).entry.id; + fileForCancelEditingId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForCancelEditing)).entry.id; + fileForUploadNewVersionId = (await apis.user.upload.uploadFileWithRename(docxFile, parentId, fileForUploadNewVersion)).entry.id; - await apis.user.favorites.addFavoritesByIds('file', [docxFileId, xlsxFileId, pdfFileId]) - await apis.user.favorites.waitForApi({expect: 3}); + await apis.user.nodes.lockFile(fileForCancelEditingId); + await apis.user.nodes.lockFile(fileForUploadNewVersionId); + await apis.user.nodes.lockFile(docxLockedId); + + await apis.user.favorites.addFavoritesByIds('file', [docxFileId, docxLockedId, xlsxFileId, pdfFileId, fileForEditOfflineId, fileForCancelEditingId, fileForUploadNewVersionId, fileFavId]) + await apis.user.favorites.waitForApi({expect: 8}); await loginPage.loginWith(username); done(); @@ -671,11 +1069,63 @@ describe('Viewer actions', () => { done(); }); + it('Correct actions appear in the viewer toolbar - [C297599]', async () => { + await dataTable.doubleClickOnRowByName(docxFavorites); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(true, `Edit offline is not displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(false, `Cancel editing is displayed`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + + it('Correct actions appear in the viewer toolbar for a locked file - [C297600]', async () => { + await dataTable.doubleClickOnRowByName(docxLockedFavorites); + await viewer.waitForViewerToOpen(); + + expect(await toolbar.isEmpty()).toBe(false, `viewer toolbar is empty`); + expect(await toolbar.isViewPresent()).toBe(false, `View is displayed`); + expect(await toolbar.isDownloadPresent()).toBe(true, `Download is not displayed`); + expect(await toolbar.isPrintPresent()).toBe(true, `Print is not displayed`); + expect(await toolbar.isFullScreenPresent()).toBe(true, `Full screen is not displayed`); + expect(await toolbar.isSharePresent()).toBe(true, `Share is not displayed`); + expect(await toolbar.isViewDetailsPresent()).toBe(true, `view details is not displayed`); + + await toolbar.openMoreMenu(); + + expect(await toolbar.menu.isEditOfflinePresent()).toBe(false, `Edit offline is displayed`); + expect(await toolbar.menu.isCancelEditingPresent()).toBe(true, `Cancel editing is not displayed`); + expect(await toolbar.menu.isToggleRemoveFavoritePresent()).toBe(true, `Remove favorite is not displayed`); + expect(await toolbar.menu.isCopyPresent()).toBe(true, `Copy is not displayed`); + expect(await toolbar.menu.isMovePresent()).toBe(true, `Move is not displayed`); + expect(await toolbar.menu.isDeletePresent()).toBe(true, `Delete is not displayed`); + expect(await toolbar.menu.isManageVersionsPresent()).toBe(true, `Manage versions is not displayed`); + expect(await toolbar.menu.isUploadNewVersionPresent()).toBe(true, `Upload new version is not displayed`); + + await toolbar.closeMoreMenu(); + }); + it('Download action - [C286390]', async () => { await dataTable.doubleClickOnRowByName(docxFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.clickButton('Download'); + await toolbar.clickDownload(); expect(await Utils.fileExistsOnOS(docxFavorites)).toBe(true, 'File not found in download location'); }); @@ -683,18 +1133,17 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(docxFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Copy'); + await toolbar.clickMoreActionsCopy(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickCopy(); expect(await page.getSnackBarMessage()).toContain('Copied 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(docxFavorites).isPresent()).toBe(true, 'Item is not in the list'); + expect(await dataTable.isItemPresent(docxFavorites)).toBe(true, 'Item is not in the list'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(docxFavorites).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(docxFavorites)).toBe(true, 'Item is not present in destination'); await apis.user.nodes.deleteNodeChildren(destinationId); done(); @@ -704,51 +1153,85 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(xlsxFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Move'); + await toolbar.clickMoreActionsMove(); expect(await copyMoveDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await copyMoveDialog.selectLocation('Personal Files'); - await copyMoveDialog.chooseDestination(destination); + await copyMoveDialog.selectDestination(destination); await copyMoveDialog.clickMove(); expect(await page.getSnackBarMessage()).toContain('Moved 1 item'); await viewer.clickClose(); - expect(await dataTable.getRowByName(xlsxFavorites).isPresent()).toBe(true, 'Item is not in the list'); - expect(await dataTable.getItemLocationTileAttr(xlsxFavorites)).toContain(destination, 'Item was not moved'); + expect(await dataTable.isItemPresent(xlsxFavorites)).toBe(true, 'Item is not in the list'); + expect(await dataTable.getItemLocationTooltip(xlsxFavorites)).toContain(destination, 'Item was not moved'); await page.clickPersonalFilesAndWait(); await dataTable.doubleClickOnRowByName(destination); - expect(await dataTable.getRowByName(xlsxFavorites).isPresent()).toBe(true, 'Item is not present in destination'); + expect(await dataTable.isItemPresent(xlsxFavorites)).toBe(true, 'Item is not present in destination'); }); it('Favorite action - [C286393]', async () => { await dataTable.doubleClickOnRowByName(xlsxFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Favorite'); + await toolbar.clickMoreActionsRemoveFavorite(); await viewer.clickClose(); await page.clickFavoritesAndWait(); expect(await apis.user.favorites.isFavorite(xlsxFileId)).toBe(false, 'Item is still favorite'); - expect(await dataTable.getRowByName(xlsxFavorites).isPresent()).toBe(false, 'Item is still present in Favorites list'); + expect(await dataTable.isItemPresent(xlsxFavorites)).toBe(false, 'Item is still present in Favorites list'); }); it('Delete action - [C286394]', async () => { await dataTable.doubleClickOnRowByName(pdfFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Delete'); + await toolbar.clickMoreActionsDelete(); expect(await page.getSnackBarMessage()).toContain(`${pdfFavorites} deleted`); expect(await viewer.isViewerOpened()).toBe(false, 'Viewer is opened'); await Utils.pressEscape(); await page.clickTrashAndWait(); - expect(await dataTable.getRowByName(pdfFavorites).isPresent()).toBe(true, 'Item is not present in Trash'); + expect(await dataTable.isItemPresent(pdfFavorites)).toBe(true, 'Item is not present in Trash'); + }); + + it('Edit Offline action - [C297604]', async () => { + await dataTable.doubleClickOnRowByName(fileForEditOffline); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsEditOffline(); + + expect(await Utils.fileExistsOnOS(fileForEditOffline)).toBe(true, 'File not found in download location'); + expect(await apis.user.nodes.isFileLockedWrite(fileForEditOfflineId)).toBe(true, `${fileForEditOffline} is not locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Cancel Editing action - [C297605]', async () => { + await dataTable.doubleClickOnRowByName(fileForCancelEditing); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsCancelEditing(); + + expect(await apis.user.nodes.isFileLockedWrite(fileForCancelEditingId)).toBe(false, `${fileForCancelEditing} is still locked`); + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + }); + + it('Upload new version action - [C297606]', async () => { + await dataTable.doubleClickOnRowByName(fileFav); + await viewer.waitForViewerToOpen(); + await toolbar.clickMoreActionsUploadNewVersion(); + + await Utils.uploadFileNewVersion(docxFile2); + await page.waitForDialog(); + + await uploadNewVersionDialog.clickMajor(); + await uploadNewVersionDialog.enterDescription('new major version description'); + await uploadNewVersionDialog.clickUpload(); + + expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not open'); + expect(await viewer.getFileTitle()).toContain(docxFile2); + expect(await apis.user.nodes.getFileVersionType(fileFavId)).toEqual('MAJOR', 'File has incorrect version type'); + expect(await apis.user.nodes.getFileVersionLabel(fileFavId)).toEqual('2.0', 'File has incorrect version label'); }); it('Share action - [C286395]', async () => { await dataTable.doubleClickOnRowByName(docxFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.clickShareButton(); + await toolbar.clickShare(); expect(await shareDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await shareDialog.clickClose(); }); @@ -757,8 +1240,7 @@ describe('Viewer actions', () => { await dataTable.doubleClickOnRowByName(docxFavorites); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); - await toolbar.openMoreMenu(); - await toolbar.menu.clickMenuItem('Manage Versions'); + await toolbar.clickMoreActionsManageVersions(); expect(await manageVersionsDialog.isDialogOpen()).toBe(true, 'Dialog is not open'); await manageVersionsDialog.clickClose(); }); diff --git a/e2e/suites/viewer/viewer-general.test.ts b/e2e/suites/viewer/viewer-general.test.ts index 2a5f72ba55..3341402230 100755 --- a/e2e/suites/viewer/viewer-general.test.ts +++ b/e2e/suites/viewer/viewer-general.test.ts @@ -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,6 @@ * along with Alfresco. If not, see . */ -import { protractor, browser } from 'protractor'; import { LoginPage, BrowsingPage } from '../../pages/pages'; import { FILES, SITE_VISIBILITY } from '../../configs'; import { RepoClient } from '../../utilities/repo-client/repo-client'; @@ -83,7 +82,7 @@ describe('Viewer general', () => { }); afterEach(async (done) => { - await browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); + await Utils.pressEscape(); done(); }); @@ -101,7 +100,7 @@ describe('Viewer general', () => { it('Viewer opens when clicking the View action for a file - [C279270]', async () => { await dataTable.selectItem(xlsxFile); - await page.toolbar.getButtonByTitleAttribute('View').click(); + await page.toolbar.clickView(); expect(await viewer.isViewerOpened()).toBe(true, 'Viewer is not opened'); }); @@ -139,7 +138,7 @@ describe('Viewer general', () => { }); it('Viewer opens for a file from File Libraries - [C284633]', async () => { - await page.clickFileLibrariesAndWait(); + await page.goToMyLibrariesAndWait(); await dataTable.doubleClickOnRowByName(siteUser); await dataTable.waitForHeader(); await dataTable.doubleClickOnRowByName(fileInSite); diff --git a/e2e/tsconfig.e2e.typecheck.json b/e2e/tsconfig.e2e.typecheck.json new file mode 100644 index 0000000000..6e22a100d4 --- /dev/null +++ b/e2e/tsconfig.e2e.typecheck.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.e2e.json", + "compilerOptions": { + "noEmit": true, + "noUnusedLocals": true + } +} diff --git a/e2e/utilities/browser-utils.ts b/e2e/utilities/browser-utils.ts index e616f1d768..3f5c0cde4d 100644 --- a/e2e/utilities/browser-utils.ts +++ b/e2e/utilities/browser-utils.ts @@ -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 diff --git a/e2e/utilities/repo-client/apis/authentication/authentication-api.ts b/e2e/utilities/repo-client/apis/authentication/authentication-api.ts index e7466c1245..2a53d3b960 100755 --- a/e2e/utilities/repo-client/apis/authentication/authentication-api.ts +++ b/e2e/utilities/repo-client/apis/authentication/authentication-api.ts @@ -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 diff --git a/src/app/components/common/name-column/name-column.component.spec.ts b/e2e/utilities/repo-client/apis/comments/comments-api.ts old mode 100644 new mode 100755 similarity index 56% rename from src/app/components/common/name-column/name-column.component.spec.ts rename to e2e/utilities/repo-client/apis/comments/comments-api.ts index daa82e385d..658a5f34d6 --- a/src/app/components/common/name-column/name-column.component.spec.ts +++ b/e2e/utilities/repo-client/apis/comments/comments-api.ts @@ -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,27 @@ * along with Alfresco. If not, see . */ -import { NameColumnComponent } from './name-column.component'; +import { RepoApi } from '../repo-api'; +import { CommentsApi as AdfCommentsApi } from '@alfresco/js-api'; -describe('NameColumnComponent', () => { - it('should be defined', () => { - expect(NameColumnComponent).toBeDefined(); - }); -}); +export class CommentsApi extends RepoApi { + commentsApi = new AdfCommentsApi(this.alfrescoJsApi); + + constructor(username?, password?) { + super(username, password); + } + + async getNodeComments(nodeId: string) { + await this.apiAuth(); + return await this.commentsApi.listComments(nodeId); + } + + async addComment(nodeId: string, comment: string) { + await this.apiAuth(); + return await this.commentsApi.createComment(nodeId, { "content": comment }); + } + async addComments(nodeId: string, comment: any) { + await this.apiAuth(); + return await this.commentsApi.createComment(nodeId, comment); + } +} diff --git a/e2e/utilities/repo-client/apis/favorites/favorites-api.ts b/e2e/utilities/repo-client/apis/favorites/favorites-api.ts index f4fb0d1ad8..3f119bb045 100755 --- a/e2e/utilities/repo-client/apis/favorites/favorites-api.ts +++ b/e2e/utilities/repo-client/apis/favorites/favorites-api.ts @@ -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,8 +26,11 @@ import { RepoApi } from '../repo-api'; import { RepoClient } from './../../repo-client'; import { Utils } from '../../../../utilities/utils'; +import { FavoritesApi as AdfFavoritesApi, SitesApi as AdfSiteApi } from '@alfresco/js-api'; export class FavoritesApi extends RepoApi { + favoritesApi = new AdfFavoritesApi(this.alfrescoJsApi); + sitesApi = new AdfSiteApi(this.alfrescoJsApi); constructor(username?, password?) { super(username, password); @@ -42,7 +45,7 @@ export class FavoritesApi extends RepoApi { } } }; - return await this.alfrescoJsApi.core.favoritesApi.addFavorite('-me-', data); + return await this.favoritesApi.createFavorite('-me-', data); } async addFavoriteById(nodeType: 'file' | 'folder' | 'site', id: string) { @@ -50,7 +53,7 @@ export class FavoritesApi extends RepoApi { await this.apiAuth(); if ( nodeType === 'site' ) { - guid = (await this.alfrescoJsApi.core.sitesApi.getSite(id)).entry.guid; + guid = (await this.sitesApi.getSite(id)).entry.guid; } else { guid = id; } @@ -61,11 +64,14 @@ export class FavoritesApi extends RepoApi { } } }; - return await this.alfrescoJsApi.core.favoritesApi.addFavorite('-me-', data); + try { + return await this.favoritesApi.createFavorite('-me-', data); + } catch (error) { + // console.log('--- add favorite by id catch '); + } } async addFavoritesByIds(nodeType: 'file' | 'folder' | 'site', ids: string[]) { - await this.apiAuth(); return await ids.reduce(async (previous, current) => { await previous; await this.addFavoriteById(nodeType, current); @@ -74,12 +80,12 @@ export class FavoritesApi extends RepoApi { async getFavorites() { await this.apiAuth(); - return await this.alfrescoJsApi.core.favoritesApi.getFavorites(this.getUsername()); + return await this.favoritesApi.listFavorites(this.getUsername()); } async getFavoriteById(nodeId: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.favoritesApi.getFavorite('-me-', nodeId); + return await this.favoritesApi.getFavorite('-me-', nodeId); } async isFavorite(nodeId: string) { @@ -90,7 +96,7 @@ export class FavoritesApi extends RepoApi { let isFavorite; try { const favorite = async () => { - isFavorite = JSON.stringify((await this.getFavorites()).list.entries).includes(nodeId); + isFavorite = await this.isFavorite(nodeId); if ( isFavorite !== data.expect ) { return Promise.reject(isFavorite); } else { @@ -107,13 +113,19 @@ export class FavoritesApi extends RepoApi { async removeFavoriteById(nodeId: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.peopleApi.removeFavoriteSite('-me-', nodeId); + try { + return await this.favoritesApi.deleteFavorite('-me-', nodeId); + } catch (error) { + // console.log('--- remove favorite by id catch '); + } } - async removeFavorite(api: RepoClient, name: string) { - const nodeId = (await api.nodes.getNodeByPath(name)).entry.id; - return await this.removeFavoriteById(nodeId); - } + async removeFavoritesByIds(ids: string[]) { + return await ids.reduce(async (previous, current) => { + await previous; + await this.removeFavoriteById(current); + }, Promise.resolve()); + } async waitForApi(data) { try { @@ -130,6 +142,5 @@ export class FavoritesApi extends RepoApi { } catch (error) { console.log('-----> catch favorites: ', error); } - } } diff --git a/e2e/utilities/repo-client/apis/nodes/node-body-create.ts b/e2e/utilities/repo-client/apis/nodes/node-body-create.ts index d82201ab2c..cbb76069b8 100755 --- a/e2e/utilities/repo-client/apis/nodes/node-body-create.ts +++ b/e2e/utilities/repo-client/apis/nodes/node-body-create.ts @@ -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 diff --git a/e2e/utilities/repo-client/apis/nodes/node-content-tree.ts b/e2e/utilities/repo-client/apis/nodes/node-content-tree.ts index 65915d4800..642e0aa76b 100755 --- a/e2e/utilities/repo-client/apis/nodes/node-content-tree.ts +++ b/e2e/utilities/repo-client/apis/nodes/node-content-tree.ts @@ -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 diff --git a/e2e/utilities/repo-client/apis/nodes/nodes-api.ts b/e2e/utilities/repo-client/apis/nodes/nodes-api.ts index 9a60adc789..52e3c9746a 100755 --- a/e2e/utilities/repo-client/apis/nodes/nodes-api.ts +++ b/e2e/utilities/repo-client/apis/nodes/nodes-api.ts @@ -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,27 +23,26 @@ * along with Alfresco. If not, see . */ -import { NodeBodyLock } from 'alfresco-js-api-node'; import { RepoApi } from '../repo-api'; import { NodeBodyCreate } from './node-body-create'; import { NodeContentTree, flattenNodeContentTree } from './node-content-tree'; +import { NodesApi as AdfNodeApi, NodeBodyLock} from '@alfresco/js-api'; export class NodesApi extends RepoApi { + nodesApi = new AdfNodeApi(this.alfrescoJsApi); constructor(username?, password?) { super(username, password); } - // nodes - async getNodeByPath(relativePath: string = '/') { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.getNode('-my-', { relativePath }); + return await this.nodesApi.getNode('-my-', { relativePath }); } async getNodeById(id: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.getNode(id); + return await this.nodesApi.getNode(id); } async getNodeDescription(name: string, parentId: string) { @@ -59,13 +58,41 @@ export class NodesApi extends RepoApi { return ''; } + async getFileVersionType(nodeId: string) { + const prop = await this.getNodeProperty(nodeId, 'cm:versionType'); + if ( prop ) { + return prop; + } + return ''; + } + async getFileVersionLabel(nodeId: string) { + const prop = await this.getNodeProperty(nodeId, 'cm:versionLabel'); + if ( prop ) { + return prop; + } + return ''; + } + + + async getSharedId(nodeId: string) { + return await this.getNodeProperty(nodeId, 'qshare:sharedId'); + } + + async getSharedExpiryDate(nodeId: string) { + return await this.getNodeProperty(nodeId, 'qshare:expiryDate'); + } + async isFileShared(nodeId: string) { - return (await this.getNodeProperty(nodeId, 'qshare:sharedId')) !== ''; + return (await this.getSharedId(nodeId)) !== ''; } async deleteNodeById(id: string, permanent: boolean = true) { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.deleteNode(id, { permanent }); + try { + return await this.nodesApi.deleteNode(id, { permanent }); + } catch (error) { + console.log('------ deleteNodeById failed '); + } } async deleteNodeByPath(path: string, permanent: boolean = true) { @@ -87,14 +114,12 @@ export class NodesApi extends RepoApi { }, Promise.resolve()); } - // children - async getNodeChildren(nodeId: string) { const opts = { include: [ 'properties' ] }; await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.getNodeChildren(nodeId, opts); + return await this.nodesApi.listNodeChildren(nodeId, opts); } async deleteNodeChildren(parentId: string) { @@ -111,7 +136,7 @@ export class NodesApi extends RepoApi { return await this.createNode('cm:content', name, parentId, title, description, imageProps); } - async createNode(nodeType: string, name: string, parentId: string = '-my-', title: string = '', description: string = '', imageProps: any = null) { + async createNode(nodeType: string, name: string, parentId: string = '-my-', title: string = '', description: string = '', imageProps: any = null, majorVersion: boolean = true) { const nodeBody = { name, nodeType, @@ -125,11 +150,11 @@ export class NodesApi extends RepoApi { } await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.addNode(parentId, nodeBody); + return await this.nodesApi.createNode(parentId, nodeBody, { majorVersion: true }); } - async createFile(name: string, parentId: string = '-my-', title: string = '', description: string = '') { - return await this.createNode('cm:content', name, parentId, title, description); + async createFile(name: string, parentId: string = '-my-', title: string = '', description: string = '', majorVersion: boolean = true) { + return await this.createNode('cm:content', name, parentId, title, description, majorVersion); } async createImage(name: string, parentId: string = '-my-', title: string = '', description: string = '') { @@ -142,7 +167,7 @@ export class NodesApi extends RepoApi { async createChildren(data: NodeBodyCreate[]): Promise { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.addNode('-my-', data); + return await this.nodesApi.createNode('-my-', data); } async createContent(content: NodeContentTree, relativePath: string = '/') { @@ -160,17 +185,17 @@ export class NodesApi extends RepoApi { // node content async getNodeContent(nodeId: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.getNodeContent(nodeId); + return await this.nodesApi.getNodeContent(nodeId); } async editNodeContent(nodeId: string, content: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.updateNodeContent(nodeId, content); + return await this.nodesApi.updateNodeContent(nodeId, content); } async renameNode(nodeId: string, newName: string) { await this.apiAuth(); - return this.alfrescoJsApi.core.nodesApi.updateNode(nodeId, { name: newName }); + return this.nodesApi.updateNode(nodeId, { name: newName }); } // node permissions @@ -188,25 +213,39 @@ export class NodesApi extends RepoApi { }; await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.updateNode(nodeId, data); + return await this.nodesApi.updateNode(nodeId, data); } async getNodePermissions(nodeId: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.getNode(nodeId, { include: ['permissions'] }); + return await this.nodesApi.getNode(nodeId, { include: ['permissions'] }); } // lock node - async lockFile(nodeId: string, lockType: string = 'FULL') { + async lockFile(nodeId: string, lockType: string = 'ALLOW_OWNER_CHANGES') { const data = { type: lockType }; + await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.lockNode(nodeId, data ); + return await this.nodesApi.lockNode(nodeId, data ); } async unlockFile(nodeId: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.unlockNode(nodeId); + return await this.nodesApi.unlockNode(nodeId); + } + + async getLockType(nodeId: string) { + return await this.getNodeProperty(nodeId, 'cm:lockType'); + } + + async getLockOwner(nodeId: string) { + return await this.getNodeProperty(nodeId, 'cm:lockOwner'); + } + + async isFileLockedWrite(nodeId: string) { + await this.apiAuth(); + return (await this.getLockType(nodeId)) === 'WRITE_LOCK'; } } diff --git a/e2e/utilities/repo-client/apis/people/people-api-models.ts b/e2e/utilities/repo-client/apis/people/people-api-models.ts index f5155843c0..153d62e149 100755 --- a/e2e/utilities/repo-client/apis/people/people-api-models.ts +++ b/e2e/utilities/repo-client/apis/people/people-api-models.ts @@ -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 diff --git a/e2e/utilities/repo-client/apis/people/people-api.ts b/e2e/utilities/repo-client/apis/people/people-api.ts index f6a7af8b11..b377db8feb 100755 --- a/e2e/utilities/repo-client/apis/people/people-api.ts +++ b/e2e/utilities/repo-client/apis/people/people-api.ts @@ -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 @@ -25,8 +25,10 @@ import { PersonModel, Person } from './people-api-models'; import { RepoApi } from '../repo-api'; +import { PeopleApi as AdfPeopleApi} from '@alfresco/js-api'; export class PeopleApi extends RepoApi { + peopleApi = new AdfPeopleApi(this.alfrescoJsApi); constructor(username?, password?) { super(username, password); @@ -35,17 +37,17 @@ export class PeopleApi extends RepoApi { async createUser(user: PersonModel) { const person = new Person(user); await this.apiAuth(); - return await this.alfrescoJsApi.core.peopleApi.addPerson(person); + return await this.peopleApi.createPerson(person); } async getUser(username: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.peopleApi.getPerson(username); + return await this.peopleApi.getPerson(username); } async updateUser(username: string, userDetails?: PersonModel) { await this.apiAuth(); - return this.alfrescoJsApi.core.peopleApi.updatePerson(username, userDetails); + return this.peopleApi.updatePerson(username, userDetails); } async disableUser(username: string) { diff --git a/e2e/utilities/repo-client/apis/queries/queries-api.ts b/e2e/utilities/repo-client/apis/queries/queries-api.ts index 87aba7bc45..0b7996ee0a 100755 --- a/e2e/utilities/repo-client/apis/queries/queries-api.ts +++ b/e2e/utilities/repo-client/apis/queries/queries-api.ts @@ -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 @@ -25,10 +25,12 @@ import { RepoApi } from '../repo-api'; import { Utils } from '../../../../utilities/utils'; +import { QueriesApi as AdfQueriesApi } from '@alfresco/js-api'; export class QueriesApi extends RepoApi { + queriesApi = new AdfQueriesApi(this.alfrescoJsApi); - constructor(username?, password?) { + constructor(username?: string, password?: string) { super(username, password); } @@ -39,10 +41,20 @@ export class QueriesApi extends RepoApi { }; await this.apiAuth(); - return this.alfrescoJsApi.core.queriesApi.findSites(searchTerm, data); + return this.queriesApi.findSites(searchTerm, data); } - async waitForApi(searchTerm, data) { + async findNodes(searchTerm: string) { + const data = { + term: searchTerm, + fields: ['name'] + }; + + await this.apiAuth(); + return this.queriesApi.findNodes(searchTerm, data); + } + + async waitForSites(searchTerm: string, data: any) { try { const sites = async () => { const totalItems = (await this.findSites(searchTerm)).list.pagination.totalItems; @@ -58,4 +70,21 @@ export class QueriesApi extends RepoApi { console.log('-----> catch queries findSites: ', error); } } + + async waitForFilesAndFolders(searchTerm: string, data: any) { + try { + const nodes = async () => { + const totalItems = (await this.findNodes(searchTerm)).list.pagination.totalItems; + if ( totalItems !== data.expect ) { + return Promise.reject(totalItems); + } else { + return Promise.resolve(totalItems); + } + }; + + return await Utils.retryCall(nodes); + } catch (error) { + console.log('-----> catch queries findFilesAndFolders: ', error); + } + } } diff --git a/e2e/utilities/repo-client/apis/repo-api.ts b/e2e/utilities/repo-client/apis/repo-api.ts index e90596a82b..1588858356 100644 --- a/e2e/utilities/repo-client/apis/repo-api.ts +++ b/e2e/utilities/repo-client/apis/repo-api.ts @@ -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,21 +23,22 @@ * along with Alfresco. If not, see . */ -import * as AlfrescoApi from 'alfresco-js-api-node'; +import { AlfrescoApi } from '@alfresco/js-api'; import { REPO_API_HOST } from '../../../configs'; import { RepoClientAuth } from '../repo-client-models'; export abstract class RepoApi { - - alfrescoJsApi = new AlfrescoApi({ - provider: 'ECM', - hostEcm: REPO_API_HOST - }); + alfrescoJsApi = new AlfrescoApi(); constructor( private username: string = RepoClientAuth.DEFAULT_USERNAME, private password: string = RepoClientAuth.DEFAULT_PASSWORD - ) {} + ) { + this.alfrescoJsApi.setConfig({ + provider: 'ECM', + hostEcm: REPO_API_HOST + }); + } apiAuth() { return this.alfrescoJsApi.login(this.username, this.password); diff --git a/e2e/utilities/repo-client/apis/search/search-api.ts b/e2e/utilities/repo-client/apis/search/search-api.ts index c1f23f4bb7..4422673733 100755 --- a/e2e/utilities/repo-client/apis/search/search-api.ts +++ b/e2e/utilities/repo-client/apis/search/search-api.ts @@ -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 @@ -25,8 +25,10 @@ import { RepoApi } from '../repo-api'; import { Utils } from '../../../../utilities/utils'; +import { SearchApi as AdfSearchApi } from '@alfresco/js-api'; export class SearchApi extends RepoApi { + searchApi = new AdfSearchApi(this.alfrescoJsApi); constructor(username?, password?) { super(username, password); @@ -46,8 +48,37 @@ export class SearchApi extends RepoApi { }; await this.apiAuth(); - return this.alfrescoJsApi.search.searchApi.search(data); + return this.searchApi.search(data); + } + + async queryNodesNames(searchTerm: string) { + const data = { + query: { + query: `cm:name:\"${searchTerm}*\"`, + language: 'afts' + }, + filterQueries: [ + { query: `+TYPE:'cm:folder' OR +TYPE:'cm:content'`} + ] + }; + + await this.apiAuth(); + return this.searchApi.search(data); + } + async queryNodesExactNames(searchTerm: string) { + const data = { + query: { + query: `cm:name:\"${searchTerm}\"`, + language: 'afts' + }, + filterQueries: [ + { query: `+TYPE:'cm:folder' OR +TYPE:'cm:content'`} + ] + }; + + await this.apiAuth(); + return this.searchApi.search(data); } async waitForApi(username, data) { @@ -66,4 +97,21 @@ export class SearchApi extends RepoApi { console.log('-----> catch search: ', error); } } + + async waitForNodes(searchTerm: string, data) { + try { + const nodes = async () => { + const totalItems = (await this.queryNodesNames(searchTerm)).list.pagination.totalItems; + if ( totalItems !== data.expect) { + return Promise.reject(totalItems); + } else { + return Promise.resolve(totalItems); + } + }; + + return await Utils.retryCall(nodes); + } catch (error) { + console.log('-----> catch search nodes: ', error); + } + } } diff --git a/e2e/utilities/repo-client/apis/shared-links/shared-links-api.ts b/e2e/utilities/repo-client/apis/shared-links/shared-links-api.ts index 09b0882231..22570ed7fd 100755 --- a/e2e/utilities/repo-client/apis/shared-links/shared-links-api.ts +++ b/e2e/utilities/repo-client/apis/shared-links/shared-links-api.ts @@ -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 @@ -25,8 +25,10 @@ import { RepoApi } from '../repo-api'; import { Utils } from '../../../../utilities/utils'; +import { SharedlinksApi as AdfSharedlinksApi } from '@alfresco/js-api'; export class SharedLinksApi extends RepoApi { + sharedlinksApi = new AdfSharedlinksApi(this.alfrescoJsApi); constructor(username?, password?) { super(username, password); @@ -39,7 +41,7 @@ export class SharedLinksApi extends RepoApi { nodeId: id, expiresAt: expireDate }; - return await this.alfrescoJsApi.core.sharedlinksApi.addSharedLink(data); + return await this.sharedlinksApi.createSharedLink(data); } catch (error) { console.log('---- shareFileById error: ', error); } @@ -60,12 +62,12 @@ export class SharedLinksApi extends RepoApi { async unshareFile(name: string) { const id = await this.getSharedIdOfNode(name); - return await this.alfrescoJsApi.core.sharedlinksApi.deleteSharedLink(id); + return await this.sharedlinksApi.deleteSharedLink(id); } async getSharedLinks() { await this.apiAuth(); - return await this.alfrescoJsApi.core.sharedlinksApi.findSharedLinks(); + return await this.sharedlinksApi.listSharedLinks(); } async waitForApi(data) { diff --git a/e2e/utilities/repo-client/apis/sites/sites-api.ts b/e2e/utilities/repo-client/apis/sites/sites-api.ts index 6bb05507af..36e3bd16bb 100755 --- a/e2e/utilities/repo-client/apis/sites/sites-api.ts +++ b/e2e/utilities/repo-client/apis/sites/sites-api.ts @@ -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 @@ -24,11 +24,13 @@ */ import { RepoApi } from '../repo-api'; -import { SiteBody, SiteMemberRoleBody, SiteMemberBody } from 'alfresco-js-api-node'; +import { SiteBody, SiteMemberRoleBody, SiteMemberBody } from '@alfresco/js-api'; import { SITE_VISIBILITY } from '../../../../configs'; import { Utils } from '../../../../utilities/utils'; +import { SitesApi as AdfSiteApi } from '@alfresco/js-api'; export class SitesApi extends RepoApi { + sitesApi = new AdfSiteApi(this.alfrescoJsApi); constructor(username?, password?) { super(username, password); @@ -36,17 +38,17 @@ export class SitesApi extends RepoApi { async getSite(siteId: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.sitesApi.getSite(siteId); + return await this.sitesApi.getSite(siteId); } async getSites() { await this.apiAuth(); - return await this.alfrescoJsApi.core.peopleApi.getSiteMembership(this.getUsername()); + return await this.sitesApi.listSiteMembershipsForPerson(this.getUsername()); } async getDocLibId(siteId: string) { await this.apiAuth(); - return (await this.alfrescoJsApi.core.sitesApi.getSiteContainers(siteId)).list.entries[0].entry.id; + return (await this.sitesApi.listSiteContainers(siteId)).list.entries[0].entry.id; } async getVisibility(siteId: string) { @@ -73,7 +75,7 @@ export class SitesApi extends RepoApi { }; await this.apiAuth(); - return await this.alfrescoJsApi.core.sitesApi.createSite(site); + return await this.sitesApi.createSite(site); } async createSites(titles: string[], visibility?: string) { @@ -85,7 +87,7 @@ export class SitesApi extends RepoApi { async deleteSite(siteId: string, permanent: boolean = true) { await this.apiAuth(); - return await this.alfrescoJsApi.core.sitesApi.deleteSite(siteId, { permanent }); + return await this.sitesApi.deleteSite(siteId, { permanent }); } async deleteSites(siteIds: string[], permanent: boolean = true) { @@ -110,7 +112,7 @@ export class SitesApi extends RepoApi { }; await this.apiAuth(); - return await this.alfrescoJsApi.core.sitesApi.updateSiteMember(siteId, userId, siteRole); + return await this.sitesApi.updateSiteMembership(siteId, userId, siteRole); } async addSiteMember(siteId: string, userId: string, role: string) { @@ -120,12 +122,12 @@ export class SitesApi extends RepoApi { }; await this.apiAuth(); - return await this.alfrescoJsApi.core.sitesApi.addSiteMember(siteId, memberBody); + return await this.sitesApi.createSiteMembership(siteId, memberBody); } async deleteSiteMember(siteId: string, userId: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.sitesApi.removeSiteMember(siteId, userId); + return await this.sitesApi.deleteSiteMembership(siteId, userId); } async requestToJoin(siteId: string) { @@ -134,7 +136,7 @@ export class SitesApi extends RepoApi { }; await this.apiAuth(); try { - return await this.alfrescoJsApi.core.peopleApi.addSiteMembershipRequest('-me-', body); + return await this.sitesApi.createSiteMembershipRequestForPerson('-me-', body); } catch (error) { console.log('====== requestToJoin catch ', error); }; @@ -142,7 +144,7 @@ export class SitesApi extends RepoApi { async hasMembershipRequest(siteId: string) { await this.apiAuth(); - const requests = (await this.alfrescoJsApi.core.peopleApi.getSiteMembershipRequests('-me-')).list.entries.map(e => e.entry.id); + const requests = (await this.sitesApi.getSiteMembershipRequests('-me-')).list.entries.map(e => e.entry.id); return requests.includes(siteId); } diff --git a/e2e/utilities/repo-client/apis/trashcan/trashcan-api.ts b/e2e/utilities/repo-client/apis/trashcan/trashcan-api.ts index 6c6a25e6d3..3879b73679 100644 --- a/e2e/utilities/repo-client/apis/trashcan/trashcan-api.ts +++ b/e2e/utilities/repo-client/apis/trashcan/trashcan-api.ts @@ -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 @@ -25,8 +25,10 @@ import { RepoApi } from '../repo-api'; import { Utils } from '../../../../utilities/utils'; +import { TrashcanApi as AdfTrashcanApi} from '@alfresco/js-api'; export class TrashcanApi extends RepoApi { + trashcanApi = new AdfTrashcanApi(this.alfrescoJsApi); constructor(username?, password?) { super(username, password); @@ -34,12 +36,12 @@ export class TrashcanApi extends RepoApi { async permanentlyDelete(id: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.purgeDeletedNode(id); + return await this.trashcanApi.deleteDeletedNode(id); } async restore(id: string) { await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.restoreNode(id); + return await this.trashcanApi.restoreDeletedNode(id); } async getDeletedNodes() { @@ -47,7 +49,7 @@ export class TrashcanApi extends RepoApi { maxItems: 1000 }; await this.apiAuth(); - return await this.alfrescoJsApi.core.nodesApi.getDeletedNodes(opts); + return await this.trashcanApi.listDeletedNodes(opts); } async emptyTrash() { diff --git a/e2e/utilities/repo-client/apis/upload/upload-api.ts b/e2e/utilities/repo-client/apis/upload/upload-api.ts index ca8762aea9..48d91a0294 100644 --- a/e2e/utilities/repo-client/apis/upload/upload-api.ts +++ b/e2e/utilities/repo-client/apis/upload/upload-api.ts @@ -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 @@ -25,10 +25,12 @@ import { RepoApi } from '../repo-api'; import { E2E_ROOT_PATH } from '../../../../configs'; +import { UploadApi as AdfUploadApi } from '@alfresco/js-api'; const fs = require('fs'); export class UploadApi extends RepoApi { + upload = new AdfUploadApi(this.alfrescoJsApi); constructor(username?, password?) { super(username, password); @@ -42,7 +44,7 @@ export class UploadApi extends RepoApi { }; await this.apiAuth(); - return await this.alfrescoJsApi.upload.uploadFile(file, '', parentFolderId, null, opts); + return await this.upload.uploadFile(file, '', parentFolderId, null, opts); } async uploadFileWithRename(fileName: string, parentFolderId: string = '-my-', newName: string) { @@ -53,7 +55,7 @@ export class UploadApi extends RepoApi { }; await this.apiAuth(); - return await this.alfrescoJsApi.upload.uploadFile(file, '', parentFolderId, null, opts); + return await this.upload.uploadFile(file, '', parentFolderId, null, opts); } } diff --git a/e2e/utilities/repo-client/repo-client-models.ts b/e2e/utilities/repo-client/repo-client-models.ts index 368151eabd..4df714dbc2 100755 --- a/e2e/utilities/repo-client/repo-client-models.ts +++ b/e2e/utilities/repo-client/repo-client-models.ts @@ -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 diff --git a/e2e/utilities/repo-client/repo-client.ts b/e2e/utilities/repo-client/repo-client.ts index d56ca241ae..bf0176ef77 100755 --- a/e2e/utilities/repo-client/repo-client.ts +++ b/e2e/utilities/repo-client/repo-client.ts @@ -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,6 +27,7 @@ import { RepoClientAuth } from './repo-client-models'; import { PeopleApi } from './apis/people/people-api'; import { NodesApi } from './apis/nodes/nodes-api'; +import { CommentsApi } from './apis/comments/comments-api'; import { SitesApi } from './apis/sites/sites-api'; import { FavoritesApi } from './apis/favorites/favorites-api'; import { QueriesApi } from './apis/queries/queries-api'; @@ -55,6 +56,10 @@ export class RepoClient { return new NodesApi(this.auth.username, this.auth.password); } + get comments() { + return new CommentsApi(this.auth.username, this.auth.password); + } + get sites() { return new SitesApi(this.auth.username, this.auth.password); } diff --git a/e2e/utilities/reporters/console/console-logger.ts b/e2e/utilities/reporters/console/console-logger.ts index 76d6683e59..9287a5ac7e 100755 --- a/e2e/utilities/reporters/console/console-logger.ts +++ b/e2e/utilities/reporters/console/console-logger.ts @@ -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 diff --git a/e2e/utilities/reporters/console/console.ts b/e2e/utilities/reporters/console/console.ts index ad08110be3..fd72697696 100755 --- a/e2e/utilities/reporters/console/console.ts +++ b/e2e/utilities/reporters/console/console.ts @@ -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 diff --git a/e2e/utilities/utils.ts b/e2e/utilities/utils.ts index ec2c4c9929..5278bfae3c 100755 --- a/e2e/utilities/utils.ts +++ b/e2e/utilities/utils.ts @@ -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,13 @@ * along with Alfresco. If not, see . */ -import { browser, protractor, promise, ElementFinder, ExpectedConditions as EC } from 'protractor'; +import { browser, protractor, promise, ElementFinder, ExpectedConditions as EC, by } from 'protractor'; import { BROWSER_WAIT_TIMEOUT, E2E_ROOT_PATH, EXTENSIBILITY_CONFIGS } from '../configs'; + const path = require('path'); const fs = require('fs'); +const StreamZip = require('node-stream-zip'); + export class Utils { static string257 = 'assembly doctor offender limit clearance inspiration baker fraud active apples trait brainstorm concept breaks down presidential \ @@ -89,15 +92,15 @@ export class Utils { } } - static async fileExistsOnOS(fileName: string) { + static async fileExistsOnOS(fileName: string, folderName: string = '', subFolderName: string = '') { const config = await browser.getProcessedConfig(); - const filePath = path.join(config.params.downloadFolder, fileName); + const filePath = path.join(config.params.downloadFolder, folderName, subFolderName, fileName); - let tries = 5; + let tries = 15; return new Promise(function(resolve) { const checkExist = setInterval(() => { - fs.stat(filePath, function(error) { + fs.access(filePath, function(error) { tries--; if (error && tries === 0) { @@ -114,20 +117,64 @@ export class Utils { }); } - static pressEscape() { - return browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); + static async renameFile(oldName: string, newName: string) { + const config = await browser.getProcessedConfig(); + const oldFilePath = path.join(config.params.downloadFolder, oldName); + const newFilePath = path.join(config.params.downloadFolder, newName); + + const fileExists = await this.fileExistsOnOS(oldName); + + if (fileExists) { + fs.rename(oldFilePath, newFilePath, function (err) { + if (err) { + console.log('==== rename err: ', err); + } + }); + } } - static pressTab() { - return browser.actions().sendKeys(protractor.Key.TAB).perform(); + static async unzip(filename: string, unzippedName: string = '') { + const config = await browser.getProcessedConfig(); + const filePath = path.join(config.params.downloadFolder, filename); + const output = path.join(config.params.downloadFolder, unzippedName ? unzippedName : ''); + + const zip = new StreamZip({ + file: filePath, + storeEntries: true + }); + + await zip.on('error', err => { console.log('=== unzip err: ', err) }); + + await zip.on('ready', async () => { + if (unzippedName) { + await fs.mkdirSync(output); + } + await zip.extract(null, output, async () => { + await zip.close(); + }); + }); } - static getBrowserLog() { - return browser.manage().logs().get('browser'); + static async pressEscape() { + return await browser.actions().sendKeys(protractor.Key.ESCAPE).perform(); + } + + static async pressTab() { + return await browser.actions().sendKeys(protractor.Key.TAB).perform(); + } + + static async getBrowserLog() { + return await browser.manage().logs().get('browser'); } static formatDate(date: string) { return new Date(date).toLocaleDateString('en-US'); } + + static async uploadFileNewVersion(fileFromOS: string) { + const el = browser.element(by.id('app-upload-file-version')); + await el.sendKeys(`${E2E_ROOT_PATH}/resources/test-files/${fileFromOS}`); + } + } diff --git a/extension.schema.json b/extension.schema.json index 5d2786a0ba..43ddee95a7 100644 --- a/extension.schema.json +++ b/extension.schema.json @@ -386,11 +386,11 @@ } }, "content-metadata-layout-group": { - "description": "Content metadata's layout groups definition", + "description": "Content metadata layout groups definition", "type": "array", "items": [ { - "description": "Content metadata's one layout group definition", + "description": "Content metadata layout group definition", "type": "object", "required": ["id"], "properties": { @@ -400,11 +400,11 @@ }, "title": { "type": "string", - "description": "Content metadata's one layout group definition's title" + "description": "Content metadata layout group definition title" }, "items": { "type": "array", - "description": "Content metadata's one layout group definition's items", + "description": "Content metadata layout group definition items", "items": { "oneOf": [ { @@ -529,6 +529,14 @@ "description": "Unique identifier.", "type": "string" }, + "disabled": { + "description": "Toggles the disabled state", + "type": "boolean" + }, + "order": { + "description": "Element order", + "type": "number" + }, "key": { "description": "Property key", "type": "string" @@ -674,12 +682,6 @@ "items": { "$ref": "#/definitions/contentActionRef" }, "minItems": 1 }, - "toolbarMoreMenu": { - "description": "Toolbar entries from the More actions menu", - "type": "array", - "items": { "$ref": "#/definitions/contentActionRef" }, - "minItems": 1 - }, "toolbarActions": { "description": "Toolbar entries from outside the More menu", "type": "array", diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index c75236b3f0..0000000000 --- a/nginx.conf +++ /dev/null @@ -1,27 +0,0 @@ -worker_processes 1; - -events { - worker_connections 1024; -} - -http { - server { - listen 80; - 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; - - access_log off; - - location / { - try_files $uri $uri/ /index.html; - } - } -} diff --git a/package-lock.json b/package-lock.json index e25bbfd101..d6b3b79e53 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,306 +1,281 @@ { "name": "alfresco-content-app", - "version": "1.6.0", + "version": "1.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@alfresco/adf-content-services": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-2.6.1.tgz", - "integrity": "sha512-mQkACzwpY4Go4MIwAMnuYp8yaQ+baiHOPfX6nJ4i+CIVnViocw8uq/lgDmSSmM4vQRr7KITh1ZOsat6rgePg6g==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@alfresco/adf-content-services/-/adf-content-services-3.0.0.tgz", + "integrity": "sha512-fslg/adVczwvrDJV4i/9zWgsrYv+zvqhmiFXubS+vORDvl48fqf3575OIfDSoeRblPrINzyoupH61DHWzAKa/w==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-core": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-2.6.1.tgz", - "integrity": "sha512-ehNQ6VNHWgj9CKrIKVuS5/7N/zqblImtXol9qZtOtHcPNvybBqdKfcbxpaedmi9eh9h4A9uEmtMJ1PvWCmfPQg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@alfresco/adf-core/-/adf-core-3.0.0.tgz", + "integrity": "sha512-3WbOGNPDM1YIG0fSQC2NiEwoNVoBU555yiW6jcNIMI6tSMVw13zuDyA9+wOmo6KY4FZlABah3hGcD/DfqBfNLg==", "requires": { "tslib": "^1.9.0" } }, "@alfresco/adf-extensions": { - "version": "3.0.0-383b74151a47e188020249aea7ec0dfb586bd0b6", - "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.0.0-383b74151a47e188020249aea7ec0dfb586bd0b6.tgz", - "integrity": "sha512-pAI4DoDMqek2G1sEFeHpgZ0OkUhSTmp95XWC+b3OoUroztwOC0y2a/PqLUvDgm5aTe4hVsA+r6IRMkp7aA1KAA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@alfresco/adf-extensions/-/adf-extensions-3.0.0.tgz", + "integrity": "sha512-piQvPQbG6Zx6J+M8U4Qv6m42gUOOOy9W3Zwgq+DdVCjP60RfhXcS+HW8wUMUxFOTgjonFOIyNA26BddIOoUhEQ==", "requires": { "tslib": "^1.9.0" } }, + "@alfresco/js-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@alfresco/js-api/-/js-api-3.0.0.tgz", + "integrity": "sha512-eiJQRJH+GHw9OszNoHWyGrc/llcI5qQBult5G3TfmRDK3c1YcCLHXbQmaN7hgoOuk0i88oPziXC6ZFS/rfi+fA==", + "requires": { + "event-emitter": "0.3.4", + "superagent": "3.8.2" + } + }, "@angular-devkit/architect": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.11.0.tgz", - "integrity": "sha512-HiMrXZ6pj4OUHmDKnLj+CIzZmr92aklBvi20QBmHv6h82l/pSs9VG5R90Dr6zHZ04cKQgKaDFJTxNQld+hHUpw==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.13.1.tgz", + "integrity": "sha512-QDmIbqde75ZZSEFbw6Q6kQWq4cY6C7D67yujXw6XTyubDNAs1tyXJyxTIB8vjSlEKwRizTTDd/B0ZXVcke3Mvw==", "dev": true, "requires": { - "@angular-devkit/core": "7.1.0", + "@angular-devkit/core": "7.3.1", "rxjs": "6.3.3" + }, + "dependencies": { + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } } }, "@angular-devkit/build-angular": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.11.0.tgz", - "integrity": "sha512-KNbVqApCfLNw7qG0i7nbirisePzcUBmqb5YJGMOEoB1pWASwGke2H/3NMTyJEDHtGDg5DdWuVvyoyXaGEKMoJg==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.11.0", - "@angular-devkit/build-optimizer": "0.11.0", - "@angular-devkit/build-webpack": "0.11.0", - "@angular-devkit/core": "7.1.0", - "@ngtools/webpack": "7.1.0", - "ajv": "6.5.3", - "autoprefixer": "9.3.1", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.13.1.tgz", + "integrity": "sha512-vkKwMVQ+NNCcVR3HFMffS+Mq4b2afXeUjI+02N38hBuFTppnC83uivUB6Uu2NUk5NTSQA4BnJlG5CbMs6N4QYg==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.13.1", + "@angular-devkit/build-optimizer": "0.13.1", + "@angular-devkit/build-webpack": "0.13.1", + "@angular-devkit/core": "7.3.1", + "@ngtools/webpack": "7.3.1", + "ajv": "6.7.0", + "autoprefixer": "9.4.6", "circular-dependency-plugin": "5.0.2", "clean-css": "4.2.1", - "copy-webpack-plugin": "4.5.4", - "file-loader": "2.0.0", + "copy-webpack-plugin": "4.6.0", + "file-loader": "3.0.1", "glob": "7.1.3", - "istanbul": "0.4.5", "istanbul-instrumenter-loader": "3.0.1", "karma-source-map-support": "1.3.0", - "less": "3.8.1", + "less": "3.9.0", "less-loader": "4.1.0", - "license-webpack-plugin": "2.0.2", - "loader-utils": "1.1.0", - "mini-css-extract-plugin": "0.4.4", + "license-webpack-plugin": "2.1.0", + "loader-utils": "1.2.3", + "mini-css-extract-plugin": "0.5.0", "minimatch": "3.0.4", - "node-sass": "4.10.0", - "opn": "5.3.0", + "node-sass": "4.11.0", + "opn": "5.4.0", "parse5": "4.0.0", - "portfinder": "1.0.17", - "postcss": "7.0.5", - "postcss-import": "12.0.0", + "postcss": "7.0.14", + "postcss-import": "12.0.1", "postcss-loader": "3.0.0", - "raw-loader": "0.5.1", + "raw-loader": "1.0.0", "rxjs": "6.3.3", "sass-loader": "7.1.0", - "semver": "5.5.1", + "semver": "5.6.0", "source-map-loader": "0.2.4", - "source-map-support": "0.5.9", - "speed-measure-webpack-plugin": "1.2.3", + "source-map-support": "0.5.10", + "speed-measure-webpack-plugin": "1.3.0", "stats-webpack-plugin": "0.7.0", "style-loader": "0.23.1", "stylus": "0.54.5", "stylus-loader": "3.0.2", - "terser-webpack-plugin": "1.1.0", - "tree-kill": "1.2.0", - "webpack": "4.23.1", - "webpack-dev-middleware": "3.4.0", - "webpack-dev-server": "3.1.10", - "webpack-merge": "4.1.4", + "terser-webpack-plugin": "1.2.2", + "tree-kill": "1.2.1", + "webpack": "4.29.0", + "webpack-dev-middleware": "3.5.1", + "webpack-dev-server": "3.1.14", + "webpack-merge": "4.2.1", "webpack-sources": "1.3.0", "webpack-subresource-integrity": "1.1.0-rc.6" }, "dependencies": { - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "optional": true - }, - "autoprefixer": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.3.1.tgz", - "integrity": "sha512-DY9gOh8z3tnCbJ13JIWaeQsoYncTGdsrgCceBaQSIL4nvdrLxgbRSBPevg2XbX7u4QCSfLheSJEEIUUSlkbx6Q==", + "@angular-devkit/architect": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.13.1.tgz", + "integrity": "sha512-QDmIbqde75ZZSEFbw6Q6kQWq4cY6C7D67yujXw6XTyubDNAs1tyXJyxTIB8vjSlEKwRizTTDd/B0ZXVcke3Mvw==", "dev": true, "requires": { - "browserslist": "^4.3.3", - "caniuse-lite": "^1.0.30000898", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^7.0.5", - "postcss-value-parser": "^3.3.1" + "@angular-devkit/core": "7.3.1", + "rxjs": "6.3.3" } }, - "caniuse-lite": { - "version": "1.0.30000912", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000912.tgz", - "integrity": "sha512-M3zAtV36U+xw5mMROlTXpAHClmPAor6GPKAMD5Yi7glCB5sbMPFtnQ3rGpk4XqPdUrrTIaVYSJZxREZWNy8QJg==", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "@angular-devkit/core": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.1.tgz", + "integrity": "sha512-56XDWWfIzOAkEk69lBLgmCYybPUA4yjunhmMlCk7vVdb7gbQUyzNjFD04Uj0GjlejatAQ5F76tRwygD9C+3RXQ==", "dev": true, - "optional": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ajv": "6.7.0", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" } }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "node-sass": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.10.0.tgz", - "integrity": "sha512-fDQJfXszw6vek63Fe/ldkYXmRYK/QS6NbvM3i5oEo9ntPDy4XX7BcKZyTKv+/kSSxRtXXc7l+MSwEmYc0CSy6Q==", - "dev": true, - "optional": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash.assign": "^4.2.0", - "lodash.clonedeep": "^4.3.2", - "lodash.mergewith": "^4.6.0", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.10.0", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "^2.2.4", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "parse5": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", "dev": true }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "tslib": "^1.9.0" } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "optional": true } } }, "@angular-devkit/build-ng-packagr": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-ng-packagr/-/build-ng-packagr-0.11.0.tgz", - "integrity": "sha512-+VO9LOFABIWEgtN92TkEiTwId++u1C+nBOHAbE+6ukfWeCnoBTHQoMX+HM92aklosSio53EuzRWiSkQphxbTcQ==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-ng-packagr/-/build-ng-packagr-0.13.1.tgz", + "integrity": "sha512-9qvdNvtlgJ3WDppbzwD9fOQzAsVogBlDeLE5zUH1ap+zcoyZEGjS1BKluiYSJ1u5Q5Nlfb3FSI/D1r9LuDQS/A==", "dev": true, "requires": { - "@angular-devkit/architect": "0.11.0", - "@angular-devkit/core": "7.1.0", + "@angular-devkit/architect": "0.13.1", + "@angular-devkit/core": "7.3.1", "rxjs": "6.3.3", - "semver": "5.5.1" + "semver": "5.6.0" }, "dependencies": { - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } } } }, "@angular-devkit/build-optimizer": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.11.0.tgz", - "integrity": "sha512-a7nIw6bN/kO77NnWoLzuoEep8jVSDxDyXZZMjvv2+bdcnua1rsScuJKII5PjGIjIucLNUJRwdHQFovVDXRMCPQ==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.13.1.tgz", + "integrity": "sha512-LmvHiI3H451aVWY5Ac6Fqz0i1eX/mUfWN+uJvo8NaL6Jc0HKYX2o3l4ODr8UUECWWctUC9AMD522ZMwAvnvsKQ==", "dev": true, "requires": { - "loader-utils": "1.1.0", + "loader-utils": "1.2.3", "source-map": "0.5.6", - "typescript": "3.1.6", - "webpack-sources": "1.2.0" + "typescript": "3.2.4", + "webpack-sources": "1.3.0" }, "dependencies": { "source-map": { "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", "dev": true }, - "webpack-sources": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz", - "integrity": "sha512-9BZwxR85dNsjWz3blyxdOhTgtnQvv3OEs5xofI0wPYTwu5kaWxS08UuD1oI7WLBLpRO+ylf0ofnXLXWmGb2WMw==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } + "typescript": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", + "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", + "dev": true } } }, "@angular-devkit/build-webpack": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.11.0.tgz", - "integrity": "sha512-AGkpHv9k9pjVEe1IihtHBWpYPSBYDEui5tFaXE6zEuXl8EbPRVW6fP4SpfEOefgCRwrUe3VP9+q5IlGgKVOXlg==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.13.1.tgz", + "integrity": "sha512-OGwC7bAl3u+w7Glw+OqIrN7OD1BkDXgrWbeQSpKAmsx6VdNPCnI4NPS+JldWNp70LVlE2nQlJUhtEqMVfBMnlg==", "dev": true, "requires": { - "@angular-devkit/architect": "0.11.0", - "@angular-devkit/core": "7.1.0", + "@angular-devkit/architect": "0.13.1", + "@angular-devkit/core": "7.3.1", "rxjs": "6.3.3" + }, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.13.1.tgz", + "integrity": "sha512-QDmIbqde75ZZSEFbw6Q6kQWq4cY6C7D67yujXw6XTyubDNAs1tyXJyxTIB8vjSlEKwRizTTDd/B0ZXVcke3Mvw==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.1", + "rxjs": "6.3.3" + } + }, + "@angular-devkit/core": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.1.tgz", + "integrity": "sha512-56XDWWfIzOAkEk69lBLgmCYybPUA4yjunhmMlCk7vVdb7gbQUyzNjFD04Uj0GjlejatAQ5F76tRwygD9C+3RXQ==", + "dev": true, + "requires": { + "ajv": "6.7.0", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" + } + }, + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + } } }, "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.1.tgz", + "integrity": "sha512-56XDWWfIzOAkEk69lBLgmCYybPUA4yjunhmMlCk7vVdb7gbQUyzNjFD04Uj0GjlejatAQ5F76tRwygD9C+3RXQ==", "dev": true, "requires": { - "ajv": "6.5.3", + "ajv": "6.7.0", "chokidar": "2.0.4", "fast-json-stable-stringify": "2.0.0", "rxjs": "6.3.3", @@ -308,9 +283,9 @@ }, "dependencies": { "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", "dev": true, "requires": { "fast-deep-equal": "^2.0.1", @@ -319,2774 +294,1360 @@ "uri-js": "^4.2.2" } }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "tslib": "^1.9.0" } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + } + } + }, + "@angular-devkit/schematics": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.3.4.tgz", + "integrity": "sha512-BLI4MDHmpzw+snu/2Dw1nMmfJ0VAARTbU6DrmzXyl2Se45+iE/tdRy4yNx3IfHhyoCrVZ15R0y9CXeEsLftlIg==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.4", + "rxjs": "6.3.3" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.4.tgz", + "integrity": "sha512-MBfen51iOBKfK4tlg5KwmPxePsF1QoFNUMGLuvUUwPkteonrGcupX1Q7NWTpf+HA+i08mOnZGuepeuQkD12IQw==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "ajv": "6.9.1", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" } }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "ajv": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "ms": "2.0.0" + "tslib": "^1.9.0" } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + } + } + }, + "@angular/animations": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.2.7.tgz", + "integrity": "sha512-eU/wSkBmukZXCCe/epUl02xsKPauF+deMbncxBE+w/NmmWjJ77Q09iZAcgzM92RVXj2LsVYQXsNEBGT3X0hRZw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/cdk": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-7.3.3.tgz", + "integrity": "sha512-0M3nwq+c9+d+p0XeU12I9djutlsajRrxcu7AvHQXUs/5grYFsXsX0f468qXDiKmcgqGUBNtN2fBOUhGNlispuQ==", + "requires": { + "parse5": "^5.0.0", + "tslib": "^1.7.1" + } + }, + "@angular/cli": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-7.3.4.tgz", + "integrity": "sha512-uGL8xiQf+GvuJvqvMUu/XHcijbq9ocbX487LO2PgJ29etHfI7dC0toJbQ8ob+HnF9e1qwMe+uu45OU4C2p+a1A==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.13.4", + "@angular-devkit/core": "7.3.4", + "@angular-devkit/schematics": "7.3.4", + "@schematics/angular": "7.3.4", + "@schematics/update": "0.13.4", + "@yarnpkg/lockfile": "1.1.0", + "ini": "1.3.5", + "inquirer": "6.2.1", + "npm-package-arg": "6.1.0", + "opn": "5.4.0", + "pacote": "9.4.0", + "semver": "5.6.0", + "symbol-observable": "1.2.0" + }, + "dependencies": { + "@angular-devkit/architect": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.13.4.tgz", + "integrity": "sha512-wJF8oz8MurtpFi0ik42bkI2F5gEnuOe79KHPO1i3SYfdhEp5NY8igVKZ6chB/eq4Ml50aHxas8Hh9ke12K+Pxw==", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "@angular-devkit/core": "7.3.4", + "rxjs": "6.3.3" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "@angular-devkit/core": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.4.tgz", + "integrity": "sha512-MBfen51iOBKfK4tlg5KwmPxePsF1QoFNUMGLuvUUwPkteonrGcupX1Q7NWTpf+HA+i08mOnZGuepeuQkD12IQw==", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "ajv": "6.9.1", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "ajv": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "tslib": "^1.9.0" } + } + } + }, + "@angular/common": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.2.7.tgz", + "integrity": "sha512-U1l2CIcmpTAJMWcyTXI9qt1E8CxwKNW1vr6XWZo4X5ziCIzf7RvClzK7Ci5KZKkoPJrJqBJu661Q75Yt22dJsg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.2.7.tgz", + "integrity": "sha512-e61YVxW5x4w+X4yjGaptYoJIja7HwH0+8FFEaH6VuPl/DrK8wP4HDMhLo4NzdgeZKLR2jBIQSqLmoM8W7UXcqw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/compiler-cli": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.2.7.tgz", + "integrity": "sha512-UPWROJzBLejgNf+aqgEUXYts8UiFOl2IavDhS/olA9irszv2lNFj9Yqr8OKdy0jK/lKaipZog3VZEx8g5dNeBA==", + "dev": true, + "requires": { + "canonical-path": "1.0.0", + "chokidar": "^2.1.1", + "convert-source-map": "^1.5.1", + "dependency-graph": "^0.7.2", + "magic-string": "^0.25.0", + "minimist": "^1.2.0", + "reflect-metadata": "^0.1.2", + "shelljs": "^0.8.1", + "source-map": "^0.6.1", + "tslib": "^1.9.0", + "yargs": "9.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "chokidar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.2.tgz", + "integrity": "sha512-IwXUx0FXc5ibYmPC2XeEj5mpXoV66sR+t3jqu2NS2GYwCktt3KF1/Qqjws/NkegajBA4RbZ5+DDwlOiJsxDHEg==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.0" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" } }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "load-json-file": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", "dev": true, "requires": { - "is-extglob": "^2.1.1" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "mimic-fn": "^1.0.0" } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" } }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@angular-devkit/schematics": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-7.1.0.tgz", - "integrity": "sha512-MIK6eT3x6EppUcz7KFwJ63z3gUVmi5dQPiN8p+kTpHE2SorZCQvQ6+YKUMw9VZ6WLEQOZYJfoQozKyEWllNlsw==", - "dev": true, - "requires": { - "@angular-devkit/core": "7.1.0", - "rxjs": "6.3.3" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", "dev": true, "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" + "pify": "^2.0.0" } }, - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" } }, - "anymatch": { + "read-pkg-up": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "ansi-regex": "^3.0.0" } }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yargs": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", + "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "camelcase": "^4.1.0" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + } + } + }, + "@angular/core": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.2.7.tgz", + "integrity": "sha512-E7qjMQdS77SbRROKu13VsfL+MJN52eTlrU0SzEAFGUOgdvbmDYJOaEwjqrouKpYZ0pul8KOoalvlPB7oVflC7A==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/flex-layout": { + "version": "7.0.0-beta.23", + "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-7.0.0-beta.23.tgz", + "integrity": "sha512-jH2i3i/M7SbK6scVlj2urVL5OhzwavbQ7KwvUjyc/UwccKnnzuOuWEGCINLja/aoaUO3I35LluCLv6a6VN0olA==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/forms": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.2.7.tgz", + "integrity": "sha512-2gBs+BG2cMPsHq9JVEzmu2Ev539zjfHmr6cna2W38KLXeGbNf42rbbMUXpYD8cndY0QTYcnwfMpRNIl9zKRZnw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/http": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.2.7.tgz", + "integrity": "sha512-HTHYF3qR4S55A+9pyThSOy7++7Makp+klbZTNmpwwJj8yL3qgy9PyDXtf+xhZcUEd8xfXmnz8s4hZr0O9GUy1A==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/language-service": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-7.2.7.tgz", + "integrity": "sha512-d3iCBpOfgLNSGMrtqZvN6NHZIEnKD2MV8Hz4WsRLU4WY0RbshZj5dqx2nO3YRT2tACpAvhWBQoYvtLpTCPzsMA==", + "dev": true + }, + "@angular/material": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-7.3.3.tgz", + "integrity": "sha512-DZdJaVpXsd5QlfpN5P871llw8AKh5QvRiyro3QRmEajYN85Xiawqpbt7O60TrwcFM6DzYLI3UeyWq8LFdmi/+Q==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/material-moment-adapter": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-7.3.3.tgz", + "integrity": "sha512-Fp2EcFpwdwa5qWWBa7G1mJZuaQ3oD3pohyo04HD2ud8YFP5IPbeoHVc65JC7TIwQFbVKk0lojXK3b2vQXZOapw==", + "requires": { + "tslib": "^1.7.1" + } + }, + "@angular/platform-browser": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.2.7.tgz", + "integrity": "sha512-9C3ffZs0ZUw+dYg1oJKiONf64UKTdAzIOaTQXTrVrCa3oN7Jb2tUfmpenmB+ATRxwhL2n7Yi725YWwxY2FwqvQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.7.tgz", + "integrity": "sha512-3nlcwCZOzlKw/4CMJ4zy1JEVy8Ky4KyLRRePLledOMdsGbuDIoq/kyAnBzg295Xe9ovBxv8cmuSkShci+s/x8g==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@angular/router": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.2.7.tgz", + "integrity": "sha512-59+M8+IH7V2NPPqWw2mwdg+kh/jfwQcXE0tB8iZ5V2ldACPucY/Td6qiT5H6t7EkELtvkKJwS6vKFV22qdRp3w==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/generator": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.3.2.tgz", + "integrity": "sha512-f3QCuPppXxtZOEm5GWPra/uYUjmNQlu9pbAD8D/9jze4pTY83rTtB1igTBSwvkeNlC5gR24zFFkz+2WHLFQhqQ==", + "dev": true, + "requires": { + "@babel/types": "^7.3.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } } }, - "@angular/animations": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-7.1.1.tgz", - "integrity": "sha512-iTNxhPPraCZsE4rgM23lguT1kDV4mfYAr+Bsi5J0+v9ZJA+VaKvi6eRW8ZGrx4/rDz6hzTnBn1jgPppHFbsOcw==", + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" } }, - "@angular/cdk": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-7.1.0.tgz", - "integrity": "sha512-dY740pKcIRtKr6n6NomrgqfdEj988urTZ9I/bfJjxF5fdhnSjyhEvDlB55EHsrF+bTTZbZXRmv7AwOQ9GJnD9w==", + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, "requires": { - "parse5": "^5.0.0", - "tslib": "^1.7.1" + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz", + "integrity": "sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" }, "dependencies": { - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "optional": true + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true } } }, - "@angular/cli": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-7.1.0.tgz", - "integrity": "sha512-G7WZvClrZjfo0VL6eFxwzqPffUQr3XbdkdCUcVbzJVnkFLrBG5Q2jFOJaZ4uFeRW4z5UM+8u/4N9N1Z6MH2QAQ==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.11.0", - "@angular-devkit/core": "7.1.0", - "@angular-devkit/schematics": "7.1.0", - "@schematics/angular": "7.1.0", - "@schematics/update": "0.11.0", - "inquirer": "6.2.0", - "opn": "5.3.0", - "semver": "5.5.1", - "symbol-observable": "1.2.0" + "@babel/parser": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.3.2.tgz", + "integrity": "sha512-QzNUC2RO1gadg+fs21fi0Uu0OuGNzRKEmgCxoLNzbCdoprLwjfmZwzUrpUNfJPaVRwBpDY47A17yYEGWyRelnQ==", + "dev": true + }, + "@babel/runtime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0.tgz", + "integrity": "sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.12.0" }, "dependencies": { - "@angular-devkit/architect": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.11.0.tgz", - "integrity": "sha512-HiMrXZ6pj4OUHmDKnLj+CIzZmr92aklBvi20QBmHv6h82l/pSs9VG5R90Dr6zHZ04cKQgKaDFJTxNQld+hHUpw==", + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + } + } + }, + "@babel/runtime-corejs2": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.3.1.tgz", + "integrity": "sha512-YpO13776h3e6Wy8dl2J8T9Qwlvopr+b4trCEhHE+yek6yIqV8sx6g3KozdHMbXeBpjosbPi+Ii5Z7X9oXFHUKA==", + "dev": true, + "requires": { + "core-js": "^2.5.7", + "regenerator-runtime": "^0.12.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", + "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==", + "dev": true + } + } + }, + "@babel/template": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.2.2.tgz", + "integrity": "sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.2.2", + "@babel/types": "^7.2.2" + } + }, + "@babel/traverse": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.2.3.tgz", + "integrity": "sha512-Z31oUD/fJvEWVR0lNZtfgvVt512ForCTNKYcJBGbPb1QZfve4WGH8Wsy7+Mev33/45fhP/hwQtvgusNdcCMgSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/generator": "^7.2.2", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.0.0", + "@babel/parser": "^7.2.3", + "@babel/types": "^7.2.2", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.10" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "@angular-devkit/core": "7.1.0", - "rxjs": "6.3.3" + "ms": "^2.1.1" } }, - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } + "globals": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.11.0.tgz", + "integrity": "sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.2.tgz", + "integrity": "sha512-3Y6H8xlUlpbGR+XvawiH0UXehqydTmNmEpozWcXymqwcrwYAl5KMvKtQ+TF6f6E08V6Jur7v/ykdDSF+WDEIXQ==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.10", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@iamstarkov/listr-update-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@iamstarkov/listr-update-renderer/-/listr-update-renderer-0.4.1.tgz", + "integrity": "sha512-IJyxQWsYDEkf8C8QthBn5N8tIUR9V9je6j3sMIpAkonaadjbvxmRC6RAhpa3RKxndhNnU2M6iNbtJwd7usQYIA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true }, - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "chalk": "^1.0.0" } }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "supports-color": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "@mat-datetimepicker/core": { + "version": "3.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-3.0.0-beta.0.tgz", + "integrity": "sha512-bsEziG0qmzVmg5PoBYqdaoUm58M1m6Qf0JIS0xHMFkvuRtLKJsA4G1LJ9Up5ZruKMW1rmtE3wuBeZmyln4vsQQ==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@mat-datetimepicker/moment": { + "version": "3.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@mat-datetimepicker/moment/-/moment-3.0.0-beta.0.tgz", + "integrity": "sha512-nWRcOi5pZ4cXzuZnjr5EMgo3UxYjuOAIAvQ10t4NQBy+0VBsbLDB8+w9DKPBZCUBfqa1oH9U1/6ai6LL4aDdtw==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@ngrx/effects": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-7.3.0.tgz", + "integrity": "sha512-PxZQaKTUmdsTPpd/0vCbYmVn8KtnvlmMDv4GflU7TVhZPe8uibaPN4HNkJMZD2gPe6qk3R7wGwuyXlFWBeQiUw==" + }, + "@ngrx/router-store": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-7.3.0.tgz", + "integrity": "sha512-CZJN0r0Te+a9tJtqX6kTeqOx2d5rmBwyjIC1g8GZfPo4rG0oIVATGTEZy/84quAJx3HhjlsqXq27nu34mDHstw==" + }, + "@ngrx/store": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-7.3.0.tgz", + "integrity": "sha512-cELOO+kHYo100Q2wi1cZqhK9jA/NJs5//0lkphoR/AKxShGmJCkub6L+qnJCrzROu4Bvod4DAlA9VAQSq4EYLg==" + }, + "@ngrx/store-devtools": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-7.3.0.tgz", + "integrity": "sha512-//zuFcXUEJO3H/KfT3ontsosdF+dBphvoT4NHHZQAewaGUmn/z6OqgJv41n0d8NmAjVmKYYA73jtWwRmfSHTcA==" + }, + "@ngtools/json-schema": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.1.0.tgz", + "integrity": "sha1-w6DFRNYjkqzCgTpCyKDcb1j4aSI=", + "dev": true + }, + "@ngtools/webpack": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.3.1.tgz", + "integrity": "sha512-EGQRjgDf5XP+Fm1MdZNRFiPd9e1vhl11BhjkwqkAsewic4eoz6fqXfj/Osz1hQy8xU+2dPPf/byQ/+nY3E02Zg==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.1", + "enhanced-resolve": "4.1.0", + "rxjs": "6.3.3", + "tree-kill": "1.2.1", + "webpack-sources": "1.3.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.1.tgz", + "integrity": "sha512-56XDWWfIzOAkEk69lBLgmCYybPUA4yjunhmMlCk7vVdb7gbQUyzNjFD04Uj0GjlejatAQ5F76tRwygD9C+3RXQ==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "ajv": "6.7.0", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" } }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "ajv": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.7.0.tgz", + "integrity": "sha512-RZXPviBTtfmtka9n9sy1N5M5b82CbxWIR6HIis4s3WQTXDJamc/0gpCWNGz6EWdWp4DOfjzJfhz/AS9zVPjjWg==", "dev": true, "requires": { - "ms": "2.0.0" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "tslib": "^1.9.0" } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + } + } + }, + "@ngx-translate/core": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-11.0.1.tgz", + "integrity": "sha512-nBCa1ZD9fAUY/3eskP3Lql2fNg8OMrYIej1/5GRsfcutx9tG/5fZLCv9m6UCw1aS+u4uK/vXjv1ctG/FdMvaWg==", + "requires": { + "tslib": "^1.9.0" + } + }, + "@phenomnomnominal/tsquery": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-3.0.0.tgz", + "integrity": "sha512-SW8lKitBHWJ9fAYkJ9kJivuctwNYCh3BUxLdH0+XiR1GPBiu+7qiZzh8p8jqlj1LgVC1TbvfNFroaEsmYlL8Iw==", + "dev": true, + "requires": { + "esquery": "^1.0.1" + } + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "dev": true, + "requires": { + "any-observable": "^0.3.0" + } + }, + "@schematics/angular": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-7.3.4.tgz", + "integrity": "sha512-Bb5DZQ8MeP8yhxPe6nVqyQ7sGVNwUx6nXPlrQV45ZycD3nJlqsuxr2DE75HFpn5oU+vlkq9J/Sys4WLJ4E/OMw==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.4", + "@angular-devkit/schematics": "7.3.4", + "typescript": "3.2.4" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.4.tgz", + "integrity": "sha512-MBfen51iOBKfK4tlg5KwmPxePsF1QoFNUMGLuvUUwPkteonrGcupX1Q7NWTpf+HA+i08mOnZGuepeuQkD12IQw==", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "ajv": "6.9.1", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "ajv": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "tslib": "^1.9.0" } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + } + } + }, + "@schematics/update": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.13.4.tgz", + "integrity": "sha512-YarSCCBSVPVG/MyN5H/FliRwaIDoeercy5Nip+NWZJsDyvtsAekO9s6QwizSvAr3541MmSQFeQICsjyM2dl3Bg==", + "dev": true, + "requires": { + "@angular-devkit/core": "7.3.4", + "@angular-devkit/schematics": "7.3.4", + "@yarnpkg/lockfile": "1.1.0", + "ini": "1.3.5", + "pacote": "9.4.0", + "rxjs": "6.3.3", + "semver": "5.6.0", + "semver-intersect": "1.4.0" + }, + "dependencies": { + "@angular-devkit/core": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.3.4.tgz", + "integrity": "sha512-MBfen51iOBKfK4tlg5KwmPxePsF1QoFNUMGLuvUUwPkteonrGcupX1Q7NWTpf+HA+i08mOnZGuepeuQkD12IQw==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "ajv": "6.9.1", + "chokidar": "2.0.4", + "fast-json-stable-stringify": "2.0.0", + "rxjs": "6.3.3", + "source-map": "0.7.3" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "ajv": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", + "integrity": "sha512-XDN92U311aINL77ieWHmqCcNlwjoP5cHXDxIxbf2MaPYuCXOHS7gHH8jktxeK5omgd52XbSTX6a4Piwd1pQmzA==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "tslib": "^1.9.0" } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true } } }, - "@angular/common": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-7.1.1.tgz", - "integrity": "sha512-SngekFx9v39sjgi9pON0Wehxpu+NdUk7OEebw4Fa8dKqTgydTkuhmnNH+9WQe264asoeCt51oufPRjIqMLNohA==", - "requires": { - "tslib": "^1.9.0" - } + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true }, - "@angular/compiler": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-7.1.1.tgz", - "integrity": "sha512-oJvBe8XZ+DXF/W/DxWBTbBcixJTuPeZWdkcZIGWhJoQP7K5GnGnj8ffP9Lp6Dh4TKv85awtC6OfIKhbHxa650Q==", + "@types/jasmine": { + "version": "2.8.16", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.16.tgz", + "integrity": "sha512-056oRlBBp7MDzr+HoU5su099s/s7wjZ3KcHxLfv+Byqb9MwdLUvsfLgw1VS97hsh3ddxSPyQu+olHMnoVTUY6g==", + "dev": true + }, + "@types/jasminewd2": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.6.tgz", + "integrity": "sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@types/jasmine": "*" } }, - "@angular/compiler-cli": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-7.1.1.tgz", - "integrity": "sha512-4NXlkDhOEQgaP3Agigqw93CvXJvsfnXa0xiglq9e/wjL+6XbtM9WcDb5lfRQz41N9RSkO3pEHGvKMweKZGgogA==", + "@types/node": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.3.0.tgz", + "integrity": "sha512-wNBfvNjzsJl4tswIZKXCFQY0lss9nKUyJnG6T94X/eqjRgI2jHZ4evdjhQYBSan/vGtF6XVXPApOmNH2rf0KKw==", + "dev": true + }, + "@types/q": { + "version": "0.0.32", + "resolved": "http://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", + "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", + "dev": true + }, + "@types/selenium-webdriver": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.14.tgz", + "integrity": "sha512-4GbNCDs98uHCT/OMv40qQC/OpoPbYn9XdXeTiFwHBBFO6eJhYEPUu2zDKirXSbHlvDV8oZ9l8EQ+HrEx/YS9DQ==", + "dev": true + }, + "@types/source-list-map": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz", + "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==", + "dev": true + }, + "@types/strip-bom": { + "version": "3.0.0", + "resolved": "http://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", + "dev": true + }, + "@types/strip-json-comments": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", + "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", + "dev": true + }, + "@types/webpack-sources": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz", + "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==", "dev": true, "requires": { - "canonical-path": "1.0.0", - "chokidar": "^1.4.2", - "convert-source-map": "^1.5.1", - "dependency-graph": "^0.7.2", - "magic-string": "^0.25.0", - "minimist": "^1.2.0", - "reflect-metadata": "^0.1.2", - "shelljs": "^0.8.1", - "source-map": "^0.6.1", - "tslib": "^1.9.0", - "yargs": "9.0.1" + "@types/node": "*", + "@types/source-list-map": "*", + "source-map": "^0.6.1" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "os-locale": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", - "dev": true, - "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" - } - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yargs": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-9.0.1.tgz", - "integrity": "sha1-UqzCP+7Kw0BCB47njAwAf1CF20w=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "read-pkg-up": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^7.0.0" - } - }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", - "dev": true, - "requires": { - "camelcase": "^4.1.0" - } } } }, - "@angular/core": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-7.1.1.tgz", - "integrity": "sha512-Osig5SRgDRQ+Hec/liN7nq/BCJieB+4/pqRh9rFbOXezb2ptgRZqdXOXN8P17i4AwPVf308Mh55V0niJ5Eu3Rw==", + "@webassemblyjs/ast": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", + "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11" } }, - "@angular/flex-layout": { - "version": "7.0.0-beta.19", - "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-7.0.0-beta.19.tgz", - "integrity": "sha512-MXq+zZ6/s5/+GsL9fZ42mKL0LjZ/+L0sVU5FaQuSAJ57soLl5QAGWvdxVmROtqcHd3Htp35R49nKSZBJ0nfAjg==", + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", + "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", + "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", + "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", + "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", + "dev": true, "requires": { - "tslib": "^1.7.1" + "@webassemblyjs/wast-printer": "1.7.11" } }, - "@angular/forms": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-7.1.1.tgz", - "integrity": "sha512-yCWuPjpu23Wc3XUw7v/ACNn/e249oT0bYlM8aaMQ1F5OwrmmC4NJC12Rpl9Ihza61RIHIKzNcHVEgzc7WhcSag==", + "@webassemblyjs/helper-fsm": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", + "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", + "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==", + "dev": true + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", + "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", + "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11" } }, - "@angular/http": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/http/-/http-7.1.1.tgz", - "integrity": "sha512-pRk+c/kz9aJ8te5xzCxlPLpFnwB0d/E9YkOo3/ydaXF9vZw13RTzk00YyzJ41PDzJf8oPDdXtueTQ+vtJ7Srtw==", + "@webassemblyjs/ieee754": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", + "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@xtuc/ieee754": "^1.2.0" } }, - "@angular/language-service": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-7.1.1.tgz", - "integrity": "sha512-X+5g20PMtNRGZIa3svMv4PLJdJehn4wqrS8nwOtzH5XkSn5vA3IxjsJVdSzAy2AN0/sKKJK5jmQorPtKO4saJg==", + "@webassemblyjs/leb128": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", + "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.1" + } + }, + "@webassemblyjs/utf8": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", + "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==", "dev": true }, - "@angular/material": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular/material/-/material-7.1.0.tgz", - "integrity": "sha512-bgotNpSfGLjNZ1AcTyhs6XS7trF4I7UHwQmfa0l8y3Gf9plwErPDfQe2XqnayRyG9nTwHj9f1lQ45X5mr3/0/A==", + "@webassemblyjs/wasm-edit": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", + "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==", + "dev": true, "requires": { - "tslib": "^1.7.1" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/helper-wasm-section": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-opt": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "@webassemblyjs/wast-printer": "1.7.11" } }, - "@angular/material-moment-adapter": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular/material-moment-adapter/-/material-moment-adapter-7.1.0.tgz", - "integrity": "sha512-4YBxsgunmbaTN+Ciefh2C3XVru1xP9OvbV1nMLz7lXvpd8bW8kuD213+rCwLOFwtpNdsGWhZYTXuhSrpoyYWhw==", + "@webassemblyjs/wasm-gen": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", + "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==", + "dev": true, "requires": { - "tslib": "^1.7.1" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" } }, - "@angular/platform-browser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-7.1.1.tgz", - "integrity": "sha512-I6OPjecynGJSbPtzu0gvEgSmIR6X6/xEAhg4L9PycW1ryjzptTC9klWRTWIqsIBqMxhVnY44uKLeRNrDwMOwyA==", + "@webassemblyjs/wasm-opt": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", + "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-buffer": "1.7.11", + "@webassemblyjs/wasm-gen": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11" } }, - "@angular/platform-browser-dynamic": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.1.1.tgz", - "integrity": "sha512-ZIu48Vn4S6gjD7CMbGlKGaPQ8v9rYkWzlNYi4vTYzgiqKKNC3hqLsVESU3mSvr5oeQBxSIBidTdHSyafHFrA2w==", + "@webassemblyjs/wasm-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", + "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-wasm-bytecode": "1.7.11", + "@webassemblyjs/ieee754": "1.7.11", + "@webassemblyjs/leb128": "1.7.11", + "@webassemblyjs/utf8": "1.7.11" } }, - "@angular/router": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-7.1.1.tgz", - "integrity": "sha512-jbnqEq/1iDBkeH8Vn13hauGPTzhwllWM+MLfmdNGTiMzGRx4pmkWa57seDOeBF/GNYBL9JjkWTCrkKFAc2FJKw==", + "@webassemblyjs/wast-parser": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", + "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/floating-point-hex-parser": "1.7.11", + "@webassemblyjs/helper-api-error": "1.7.11", + "@webassemblyjs/helper-code-frame": "1.7.11", + "@webassemblyjs/helper-fsm": "1.7.11", + "@xtuc/long": "4.2.1" } }, - "@mat-datetimepicker/core": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@mat-datetimepicker/core/-/core-2.0.1.tgz", - "integrity": "sha1-4NsdtdTPe6Vrck7AQIF8totXdfI=", + "@webassemblyjs/wast-printer": { + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", + "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/wast-parser": "1.7.11", + "@xtuc/long": "4.2.1" } }, - "@mat-datetimepicker/moment": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@mat-datetimepicker/moment/-/moment-2.0.1.tgz", - "integrity": "sha1-Yr0WQ23j2ds9roFyEYNMMpqdhvA=", + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", + "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "dev": true + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" } }, - "@ngrx/effects": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-6.1.2.tgz", - "integrity": "sha512-RUuQ5/7ofxGEZnRRdlC1oE9ugVlTYGm92MVj7c6IirHrVN9W5yQjjMTYEYceVCDOYsiXP7Pyw0dcPp6J5wD2EQ==" + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true }, - "@ngrx/router-store": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@ngrx/router-store/-/router-store-6.1.2.tgz", - "integrity": "sha512-sj083ZYrx0aY+vU/t8Ub0KYDHcMpatXJIOJR/eDNSuH54fPiBM9MrdI3hs/XHoXHxSaHOJoZ7f6I8XcUeptxyA==" + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "dev": true, + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } }, - "@ngrx/store": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-6.1.2.tgz", - "integrity": "sha512-W9MbXrwhIRmN1BlINF9BT+rHR046e1HNk7GqykcDJrK9wW74PJW3aE5iuPb2sTPipBMjPHsXzc73E4U/+OTAyw==" + "acorn": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.0.tgz", + "integrity": "sha512-MW/FjM+IvU9CgBzjO3UIPCE2pyEwUsoFl+VGdczOPEdxfGFjuKny/gN54mOuX7Qxmb9Rg9MCn2oKiSUeW+pjrw==", + "dev": true }, - "@ngrx/store-devtools": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@ngrx/store-devtools/-/store-devtools-6.1.2.tgz", - "integrity": "sha512-hvWMKcRIAtAFb2lb4woRenPHPgOiLFjy8R2PtCiw4uP3WrBVB4JHqUuP230/iRMcU5XmySp+LhNqhkk1zsoUqQ==" + "acorn-dynamic-import": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", + "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==", + "dev": true }, - "@ngtools/json-schema": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@ngtools/json-schema/-/json-schema-1.1.0.tgz", - "integrity": "sha1-w6DFRNYjkqzCgTpCyKDcb1j4aSI=", + "adm-zip": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", + "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", "dev": true }, - "@ngtools/webpack": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-7.1.0.tgz", - "integrity": "sha512-U4+2fPEEdvQN6/SmdlNYiuuwWbSEUP3Rpfbkzj7hYOHMQHnWA90u6EfZLjoyE77qqhF3EGXszjmZnYls78/c7Q==", + "after": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", + "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", + "dev": true + }, + "agent-base": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", + "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", "dev": true, "requires": { - "@angular-devkit/core": "7.1.0", - "enhanced-resolve": "4.1.0", - "rxjs": "6.3.3", - "tree-kill": "1.2.0", - "webpack-sources": "1.2.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "webpack-sources": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.2.0.tgz", - "integrity": "sha512-9BZwxR85dNsjWz3blyxdOhTgtnQvv3OEs5xofI0wPYTwu5kaWxS08UuD1oI7WLBLpRO+ylf0ofnXLXWmGb2WMw==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - } - } + "es6-promisify": "^5.0.0" } }, - "@ngx-translate/core": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-10.0.2.tgz", - "integrity": "sha512-7nM3DrJaqKswwtJlbu2kuKNl+hE8Isr18sKsKvGGpSxQk+G0gO0reDlx2PhUNus7TJTkA1C59vU/JoN8hIvZ4g==", + "agentkeepalive": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", + "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "dev": true, "requires": { - "tslib": "^1.9.0" + "humanize-ms": "^1.2.1" } }, - "@phenomnomnominal/tsquery": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-3.0.0.tgz", - "integrity": "sha512-SW8lKitBHWJ9fAYkJ9kJivuctwNYCh3BUxLdH0+XiR1GPBiu+7qiZzh8p8jqlj1LgVC1TbvfNFroaEsmYlL8Iw==", - "dev": true, + "ajv": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.8.1.tgz", + "integrity": "sha512-eqxCp82P+JfqL683wwsL73XmFs1eG6qjw+RD3YHx+Jll1r0jNd4dh8QG9NYAeNGA/hnZjeEDgtTskgJULbxpWQ==", "requires": { - "esquery": "^1.0.1" + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "@schematics/angular": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-7.1.0.tgz", - "integrity": "sha512-BLRTHlhYXgP49OwDyoolwolf7LqxOAPuc8lpgH0HEmYjkXmufZ4urngyFKY1IuBwaAR4PLjDx3U/ofszyV0taw==", + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.3.0.tgz", + "integrity": "sha512-CMzN9S62ZOO4sA/mJZIO4S++ZM7KFWzH3PPWkveLhy4OZ9i1/VatgwWMD46w/XbGCBy7Ye0gCk+Za6mmyfKK7g==" + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", "dev": true, "requires": { - "@angular-devkit/core": "7.1.0", - "@angular-devkit/schematics": "7.1.0", - "typescript": "3.1.6" + "string-width": "^2.0.0" }, "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" } }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@schematics/update": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.11.0.tgz", - "integrity": "sha512-Zrt4MQOM8DjK7fYVrzx08KhQ7jSj/at0/uF+Ca+ObZJIiC67IY8NXlc1TETXpB4A2UYrclvc9mTpZrvgIoEcYA==", - "dev": true, - "requires": { - "@angular-devkit/core": "7.1.0", - "@angular-devkit/schematics": "7.1.0", - "@yarnpkg/lockfile": "1.1.0", - "ini": "1.3.5", - "pacote": "9.1.1", - "rxjs": "6.3.3", - "semver": "5.5.1", - "semver-intersect": "1.4.0" - }, - "dependencies": { - "@angular-devkit/core": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-7.1.0.tgz", - "integrity": "sha512-mR0YNRBEWfK3y5JfPmENw6Qy8kk6jaJTjDOso1uOwRKWQDe642tnK0P1HTmZ+WBgp+RhYD4pHbKePqOHw/tsdQ==", - "dev": true, - "requires": { - "ajv": "6.5.3", - "chokidar": "2.0.4", - "fast-json-stable-stringify": "2.0.0", - "rxjs": "6.3.3", - "source-map": "0.7.3" - } - }, - "ajv": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.3.tgz", - "integrity": "sha512-LqZ9wY+fx3UMiiPd741yB2pj3hhil+hQc8taf4o2QGRFpWgZ2V5C8HA165DY9sS3fJwsk7uT7ZlFEyC3Ig3lLg==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "semver": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", - "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "@types/jasmine": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.8.tgz", - "integrity": "sha512-OJSUxLaxXsjjhob2DBzqzgrkLmukM3+JMpRp0r0E4HTdT1nwDCWhaswjYxazPij6uOdzHCJfNbDjmQ1/rnNbCg==", - "dev": true - }, - "@types/jasminewd2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/jasminewd2/-/jasminewd2-2.0.3.tgz", - "integrity": "sha512-hYDVmQZT5VA2kigd4H4bv7vl/OhlympwREUemqBdOqtrYTo5Ytm12a5W5/nGgGYdanGVxj0x/VhZ7J3hOg/YKg==", - "dev": true, - "requires": { - "@types/jasmine": "*" - } - }, - "@types/node": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.3.0.tgz", - "integrity": "sha512-wNBfvNjzsJl4tswIZKXCFQY0lss9nKUyJnG6T94X/eqjRgI2jHZ4evdjhQYBSan/vGtF6XVXPApOmNH2rf0KKw==", - "dev": true - }, - "@types/q": { - "version": "0.0.32", - "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", - "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=", - "dev": true - }, - "@types/selenium-webdriver": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz", - "integrity": "sha512-ikB0JHv6vCR1KYUQAzTO4gi/lXLElT4Tx+6De2pc/OZwizE9LRNiTa+U8TBFKBD/nntPnr/MPSHSnOTybjhqNA==", - "dev": true - }, - "@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=", - "dev": true - }, - "@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.10.tgz", - "integrity": "sha512-wTUeaByYN2EA6qVqhbgavtGc7fLTOx0glG2IBsFlrFG51uXIGlYBTyIZMf4SPLo3v1bgV/7lBN3l7Z0R6Hswew==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.7.10", - "@webassemblyjs/helper-wasm-bytecode": "1.7.10", - "@webassemblyjs/wast-parser": "1.7.10" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.10.tgz", - "integrity": "sha512-gMsGbI6I3p/P1xL2UxqhNh1ga2HCsx5VBB2i5VvJFAaqAjd2PBTRULc3BpTydabUQEGlaZCzEUQhLoLG7TvEYQ==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.10.tgz", - "integrity": "sha512-DoYRlPWtuw3yd5BOr9XhtrmB6X1enYF0/54yNvQWGXZEPDF5PJVNI7zQ7gkcKfTESzp8bIBWailaFXEK/jjCsw==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.10.tgz", - "integrity": "sha512-+RMU3dt/dPh4EpVX4u5jxsOlw22tp3zjqE0m3ftU2tsYxnPULb4cyHlgaNd2KoWuwasCQqn8Mhr+TTdbtj3LlA==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.10.tgz", - "integrity": "sha512-UiytbpKAULOEab2hUZK2ywXen4gWJVrgxtwY3Kn+eZaaSWaRM8z/7dAXRSoamhKFiBh1uaqxzE/XD9BLlug3gw==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.7.10" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.10.tgz", - "integrity": "sha512-w2vDtUK9xeSRtt5+RnnlRCI7wHEvLjF0XdnxJpgx+LJOvklTZPqWkuy/NhwHSLP19sm9H8dWxKeReMR7sCkGZA==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.10.tgz", - "integrity": "sha512-yE5x/LzZ3XdPdREmJijxzfrf+BDRewvO0zl8kvORgSWmxpRrkqY39KZSq6TSgIWBxkK4SrzlS3BsMCv2s1FpsQ==", - "dev": true - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.10.tgz", - "integrity": "sha512-u5qy4SJ/OrxKxZqJ9N3qH4ZQgHaAzsopsYwLvoWJY6Q33r8PhT3VPyNMaJ7ZFoqzBnZlCcS/0f4Sp8WBxylXfg==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.10.tgz", - "integrity": "sha512-Ecvww6sCkcjatcyctUrn22neSJHLN/TTzolMGG/N7S9rpbsTZ8c6Bl98GpSpV77EvzNijiNRHBG0+JO99qKz6g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.10", - "@webassemblyjs/helper-buffer": "1.7.10", - "@webassemblyjs/helper-wasm-bytecode": "1.7.10", - "@webassemblyjs/wasm-gen": "1.7.10" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.10.tgz", - "integrity": "sha512-HRcWcY+YWt4+s/CvQn+vnSPfRaD4KkuzQFt5MNaELXXHSjelHlSEA8ZcqT69q0GTIuLWZ6JaoKar4yWHVpZHsQ==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.10.tgz", - "integrity": "sha512-og8MciYlA8hvzCLR71hCuZKPbVBfLQeHv7ImKZ4nlyxrYbG7uJHYtHiHu6OV9SqrGuD03H/HtXC4Bgdjfm9FHw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.1" - } - }, - "@webassemblyjs/utf8": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.10.tgz", - "integrity": "sha512-Ng6Pxv6siyZp635xCSnH3mKmIFgqWPCcGdoo0GBYgyGdxu7cUj4agV7Uu1a8REP66UYUFXJLudeGgd4RvuJAnQ==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.10.tgz", - "integrity": "sha512-e9RZFQlb+ZuYcKRcW9yl+mqX/Ycj9+3/+ppDI8nEE/NCY6FoK8f3dKBcfubYV/HZn44b+ND4hjh+4BYBt+sDnA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.10", - "@webassemblyjs/helper-buffer": "1.7.10", - "@webassemblyjs/helper-wasm-bytecode": "1.7.10", - "@webassemblyjs/helper-wasm-section": "1.7.10", - "@webassemblyjs/wasm-gen": "1.7.10", - "@webassemblyjs/wasm-opt": "1.7.10", - "@webassemblyjs/wasm-parser": "1.7.10", - "@webassemblyjs/wast-printer": "1.7.10" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.10.tgz", - "integrity": "sha512-M0lb6cO2Y0PzDye/L39PqwV+jvO+2YxEG5ax+7dgq7EwXdAlpOMx1jxyXJTScQoeTpzOPIb+fLgX/IkLF8h2yw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.10", - "@webassemblyjs/helper-wasm-bytecode": "1.7.10", - "@webassemblyjs/ieee754": "1.7.10", - "@webassemblyjs/leb128": "1.7.10", - "@webassemblyjs/utf8": "1.7.10" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.10.tgz", - "integrity": "sha512-R66IHGCdicgF5ZliN10yn5HaC7vwYAqrSVJGjtJJQp5+QNPBye6heWdVH/at40uh0uoaDN/UVUfXK0gvuUqtVg==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.10", - "@webassemblyjs/helper-buffer": "1.7.10", - "@webassemblyjs/wasm-gen": "1.7.10", - "@webassemblyjs/wasm-parser": "1.7.10" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.10.tgz", - "integrity": "sha512-AEv8mkXVK63n/iDR3T693EzoGPnNAwKwT3iHmKJNBrrALAhhEjuPzo/lTE4U7LquEwyvg5nneSNdTdgrBaGJcA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.10", - "@webassemblyjs/helper-api-error": "1.7.10", - "@webassemblyjs/helper-wasm-bytecode": "1.7.10", - "@webassemblyjs/ieee754": "1.7.10", - "@webassemblyjs/leb128": "1.7.10", - "@webassemblyjs/utf8": "1.7.10" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.10.tgz", - "integrity": "sha512-YTPEtOBljkCL0VjDp4sHe22dAYSm3ZwdJ9+2NTGdtC7ayNvuip1wAhaAS8Zt9Q6SW9E5Jf5PX7YE3XWlrzR9cw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.10", - "@webassemblyjs/floating-point-hex-parser": "1.7.10", - "@webassemblyjs/helper-api-error": "1.7.10", - "@webassemblyjs/helper-code-frame": "1.7.10", - "@webassemblyjs/helper-fsm": "1.7.10", - "@xtuc/long": "4.2.1" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.7.10", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.10.tgz", - "integrity": "sha512-mJ3QKWtCchL1vhU/kZlJnLPuQZnlDOdZsyP0bbLWPGdYsQDnSBvyTLhzwBA3QAMlzEL9V4JHygEmK6/OTEyytA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.7.10", - "@webassemblyjs/wast-parser": "1.7.10", - "@xtuc/long": "4.2.1" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", - "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", - "dev": true - }, - "@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true - }, - "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", - "dev": true, - "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" - } - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", - "dev": true, - "requires": { - "acorn": "^5.0.0" - } - }, - "adm-zip": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz", - "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==", - "dev": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", - "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", - "dev": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "ajv": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", - "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.1" - } - }, - "ajv-errors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.0.tgz", - "integrity": "sha1-7PAh+hCP0X37Xms4Py3SM+Mf/Fk=", - "dev": true - }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=" - }, - "alfresco-js-api": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/alfresco-js-api/-/alfresco-js-api-2.6.1.tgz", - "integrity": "sha512-E1maHlxlFS3DAmYWG9ueerMWgrcbJSVFO52Bfk2XGx3atEnH3iBFuG0ZczfCJCGIbtv22VliR5qQ90Cufuzhkw==", - "requires": { - "event-emitter": "0.3.4", - "superagent": "3.8.2" - } - }, - "alfresco-js-api-node": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/alfresco-js-api-node/-/alfresco-js-api-node-2.6.0.tgz", - "integrity": "sha512-ETZKZzWBsZ2ztR4b4vKOne97jQrsrfsoNvVPQRxNV+Tc3zzR42OJIpIg0t48g1jdaaHmjzim8NUtafs07GhzPg==", - "dev": true, - "requires": { - "event-emitter": "0.3.4", - "superagent": "3.8.2" - } - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "requires": { - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^3.0.0" } } } }, "ansi-colors": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.1.tgz", - "integrity": "sha512-Xt+zb6nqgvV9SWAVp0EG3lRsHcbq5DDgqjPPz6pwgtj6RKz65zGXMNa82oJfOSBA/to6GmRP7Dr+6o+kbApTzQ==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", "dev": true }, "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true }, "ansi-html": { @@ -3108,33 +1669,22 @@ "dev": true, "requires": { "color-convert": "^1.9.0" - }, - "dependencies": { - "color-convert": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", - "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", - "dev": true, - "requires": { - "color-name": "1.1.1" - } - }, - "color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", - "dev": true - } } }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", + "dev": true + }, "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" } }, "app-root-path": { @@ -3178,13 +1728,10 @@ } }, "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true }, "arr-flatten": { "version": "1.1.0", @@ -3205,9 +1752,9 @@ "dev": true }, "array-flatten": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", - "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", "dev": true }, "array-slice": { @@ -3232,9 +1779,9 @@ "dev": true }, "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "arraybuffer.slice": { @@ -3292,7 +1839,7 @@ }, "util": { "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -3314,12 +1861,12 @@ "dev": true }, "async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "lodash": "^4.17.10" + "lodash": "^4.17.11" } }, "async-each": { @@ -3346,23 +1893,23 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "atob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz", - "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, "autoprefixer": { - "version": "9.1.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.1.5.tgz", - "integrity": "sha512-kk4Zb6RUc58ld7gdosERHMF3DzIYJc2fp5sX46qEsGXQQy5bXsu8qyLjoxuY1NuQ/cJuCYnx99BfjwnRggrYIw==", + "version": "9.4.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.4.6.tgz", + "integrity": "sha512-Yp51mevbOEdxDUy5WjiKtpQaecqYq9OqZSL04rSoCiry7Tc5I9FEyo3bfxiTJc1DfHeKwSFCUYbBAiOQ2VGfiw==", "dev": true, "requires": { - "browserslist": "^4.1.0", - "caniuse-lite": "^1.0.30000884", + "browserslist": "^4.4.1", + "caniuse-lite": "^1.0.30000929", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^7.0.2", - "postcss-value-parser": "^3.2.3" + "postcss": "^7.0.13", + "postcss-value-parser": "^3.3.1" } }, "aws-sign2": { @@ -3372,9 +1919,9 @@ "dev": true }, "aws4": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", - "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", "dev": true }, "babel-code-frame": { @@ -3396,7 +1943,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -3429,6 +1976,14 @@ "lodash": "^4.17.4", "source-map": "^0.5.7", "trim-right": "^1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "babel-messages": { @@ -3440,6 +1995,25 @@ "babel-runtime": "^6.22.0" } }, + "babel-polyfill": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", + "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "core-js": "^2.4.0", + "regenerator-runtime": "^0.10.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, "babel-runtime": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", @@ -3488,6 +2062,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -3572,18 +2152,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -3616,7 +2184,6 @@ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, - "optional": true, "requires": { "tweetnacl": "^0.14.3" } @@ -3631,20 +2198,20 @@ } }, "big.js": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", + "integrity": "sha512-EgmjVLMn22z7eGGv3kcnHwSnJXmFHjISTY9E/S5lIcTD3Oxw05QTcBLNkJFzcb3cNueUdF/IN4U+d78V0zO8Hw==", "dev": true }, "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", "dev": true }, "block-stream": { @@ -3663,20 +2230,12 @@ "dev": true, "requires": { "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", "dev": true }, "bn.js": { @@ -3686,21 +2245,21 @@ "dev": true }, "body-parser": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", - "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", "dev": true, "requires": { "bytes": "3.0.0", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", - "iconv-lite": "0.4.19", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", "on-finished": "~2.3.0", - "qs": "6.5.1", - "raw-body": "2.3.2", - "type-is": "~1.6.15" + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" }, "dependencies": { "debug": { @@ -3712,16 +2271,16 @@ "ms": "2.0.0" } }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true } } @@ -3761,6 +2320,12 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -3798,14 +2363,32 @@ } }, "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "brorand": { @@ -3816,7 +2399,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -3853,7 +2436,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -3886,43 +2469,20 @@ } }, "browserslist": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.3.3.tgz", - "integrity": "sha512-6h84UD1mmHeuQ9IucX6yzBc+KBYcBBTLYt2CXtY7GYCra6iE5kOm7oM+zuGw/0tjGtbJxjm58OvxSBmogEMCRQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.4.1.tgz", + "integrity": "sha512-pEBxEXg7JwaakBXjATYw/D1YZh4QUSCX/Mnd/wnqSRPPSi1U39iDhDoKGoBUcraKdxDlrYqJxSI5nNvD+dWP2A==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000898", - "electron-to-chromium": "^1.3.81", - "node-releases": "^1.0.0-alpha.15" - }, - "dependencies": { - "caniuse-lite": { - "version": "1.0.30000899", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000899.tgz", - "integrity": "sha512-enC3zKfUCJxxwvUIsBkbHd54CtJw1KtIWvrK0JZxWD/fEN2knHaai45lndJ4xXAkyRAPyk60J3yagkKDWhfeMA==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.3.82", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.82.tgz", - "integrity": "sha512-NI4nB2IWGcU4JVT1AE8kBb/dFor4zjLHMLsOROPahppeHrR0FG5uslxMmkp/thO1MvPjM2xhlKoY29/I60s0ew==", - "dev": true - }, - "node-releases": { - "version": "1.0.0-alpha.15", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.0.0-alpha.15.tgz", - "integrity": "sha512-hKG6hd/g6a9OV/ARt2qrxbRhe/4WEMFohTLOB9PNyTYvvI59gICZFzt9/mMgpYUTts06qXlN8H6UjfbIRdnW8A==", - "dev": true, - "requires": { - "semver": "^5.3.0" - } - } + "caniuse-lite": "^1.0.30000929", + "electron-to-chromium": "^1.3.103", + "node-releases": "^1.1.3" } }, "browserstack": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.1.tgz", - "integrity": "sha512-O8VMT64P9NOLhuIoD4YngyxBURefaSdR4QdhG8l6HZ9VxtU7jc3m6jLufFwKA5gaf7fetfB2TnRJnMxyob+heg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.2.tgz", + "integrity": "sha512-+6AFt9HzhKykcPF79W6yjEUJcdvZOV0lIXdkORXMJftGrDl0OKWqRF4GHqpDNkxiceDT/uB7Fb/aDwktvXX7dg==", "dev": true, "requires": { "https-proxy-agent": "^2.2.1" @@ -3930,7 +2490,7 @@ }, "buffer": { "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", "dev": true, "requires": { @@ -4005,7 +2565,7 @@ }, "cacache": { "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", + "resolved": "http://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", "dev": true, "requires": { @@ -4039,14 +2599,24 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } + } + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + } + }, + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" } }, "callsite": { @@ -4055,34 +2625,32 @@ "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", "dev": true }, + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true }, "camelcase-keys": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { "camelcase": "^2.0.0", "map-obj": "^1.0.0" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - } } }, "caniuse-lite": { - "version": "1.0.30000885", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000885.tgz", - "integrity": "sha512-cXKbYwpxBLd7qHyej16JazPoUacqoVuDhvR61U7Fr5vSxMUiodzcYa1rQYRYfZ5GexV03vGZHd722vNPLjPJGQ==", + "version": "1.0.30000935", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000935.tgz", + "integrity": "sha512-1Y2uJ5y56qDt3jsDTdBHL1OqiImzjoQcBG6Yl3Qizq8mcc2SgCFpi+ZwLLqkztYnk9l87IYqRlNBnPSOTbFkXQ==", "dev": true }, "canonical-path": { @@ -4103,26 +2671,26 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "chardet": { @@ -4132,20 +2700,24 @@ "dev": true }, "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", "dev": true, "requires": { - "anymatch": "^1.3.0", + "anymatch": "^2.0.0", "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", "inherits": "^2.0.1", "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" + "readdirp": "^2.0.0", + "upath": "^1.0.5" } }, "chownr": { @@ -4204,9 +2776,9 @@ "dev": true }, "circular-json": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.5.tgz", - "integrity": "sha512-13YaR6kiz0kBNmIVM87Io8Hp7bWOo4r61vkEANy8iH9R9bc6avud/1FT0SBpqR1RpIQADOh/Q+yHZDA1iL6ysA==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", + "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", "dev": true }, "class-utils": { @@ -4229,12 +2801,6 @@ "requires": { "is-descriptor": "^0.1.0" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true } } }, @@ -4270,6 +2836,16 @@ "restore-cursor": "^2.0.0" } }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "dev": true, + "requires": { + "slice-ansi": "0.0.4", + "string-width": "^1.0.1" + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", @@ -4303,23 +2879,6 @@ "is-plain-object": "^2.0.4", "kind-of": "^6.0.0", "shallow-clone": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } } }, "co": { @@ -4348,10 +2907,16 @@ "sprintf-js": "^1.1.1" }, "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, "sprintf-js": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", - "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", "dev": true } } @@ -4366,9 +2931,24 @@ "object-visit": "^1.0.0" } }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "colors": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "resolved": "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz", "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true }, @@ -4382,17 +2962,17 @@ } }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", "requires": { "delayed-stream": "~1.0.0" } }, "commander": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.16.0.tgz", - "integrity": "sha512-sVXqklSaotK9at437sFlFpyOcJonxe0yST/AG9DkQKUdIE6IqGIMv4SfAQSKaJbSdVEJYItASCrBiVQHq1HQew==", + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", "dev": true }, "comment-json": { @@ -4411,9 +2991,9 @@ "dev": true }, "compare-versions": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.3.0.tgz", - "integrity": "sha512-MAAAIOdi2s4Gl6rZ76PNcUa9IOYB+5ICdT41o5uMRf09aEu/F9RK+qhe8RjXNPwcTjGV7KU7h2P/fljThFVqyQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz", + "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==", "dev": true }, "component-bind": { @@ -4440,14 +3020,6 @@ "dev": true, "requires": { "mime-db": ">= 1.36.0 < 2" - }, - "dependencies": { - "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", - "dev": true - } } }, "compression": { @@ -4473,6 +3045,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -4494,23 +3072,9 @@ } }, "configstore": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", - "dev": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "configstore-fork": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/configstore-fork/-/configstore-fork-3.1.6.tgz", - "integrity": "sha512-sQ31B6Ayj9Tqs2nPBrq+2cg8j9sb1Hd6iyqDx2rH+W1EoBDevYAkLk5ncNqktkj7hCeyrUzcNhQ5kUozKXd75A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", + "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", "dev": true, "requires": { "dot-prop": "^4.1.0", @@ -4557,6 +3121,12 @@ "unpipe": "~1.0.0" } }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "statuses": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", @@ -4566,9 +3136,9 @@ } }, "connect-history-api-fallback": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", - "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", "dev": true }, "console-browserify": { @@ -4651,9 +3221,9 @@ "dev": true }, "copy-webpack-plugin": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.5.4.tgz", - "integrity": "sha512-0lstlEyj74OAtYMrDxlNZsU7cwFijAI3Ofz2fD6Mpo9r4xCv4yegfa3uHIKvZY1NSuOtE9nvG6TAhJ+uz9gDaQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", + "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==", "dev": true, "requires": { "cacache": "^10.0.4", @@ -4664,29 +3234,12 @@ "minimatch": "^3.0.4", "p-limit": "^1.0.0", "serialize-javascript": "^1.4.0" - }, - "dependencies": { - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - } } }, "core-js": { - "version": "2.5.7", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", - "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.3.tgz", + "integrity": "sha512-l00tmFFZOBHtYhN4Cz7k32VM7vTn3rE2ANjQDxdEN6zmXZ/xq1jQuutnmHvMG1ZJ7xd72+TA5YpUK8wz3rWsfQ==" }, "core-util-is": { "version": "1.0.2", @@ -4717,6 +3270,18 @@ } } }, + "cpr": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cpr/-/cpr-3.0.1.tgz", + "integrity": "sha1-uaVQOLfNgaNcF7l2GJW9hJau8eU=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.5", + "minimist": "^1.2.0", + "mkdirp": "~0.5.1", + "rimraf": "^2.5.4" + } + }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -4738,7 +3303,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -4751,7 +3316,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -4799,179 +3364,244 @@ "dev": true }, "cspell": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-3.1.3.tgz", - "integrity": "sha512-7N+ssYKkeYrwGRGlScUh3HvEePseY7VIHUpQwpMjDCdcRD91hUfuvphJEbvkWY++s4qjIF2w+9ZWcDO06sqPOQ==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-3.2.1.tgz", + "integrity": "sha512-VjEcxU+WUfJn1/ShgYVsH4fdT8MaOBmLATKZ2DpsY+zdh5i07NmC8fVlsF56F4rE5Ybz2e9KHMi+HcNN08ruEg==", "dev": true, "requires": { - "chalk": "^2.4.1", - "commander": "^2.15.1", + "chalk": "^2.4.2", + "commander": "^2.19.0", "comment-json": "^1.1.3", - "configstore-fork": "^3.1.6", - "cspell-dict-cpp": "^1.1.8", - "cspell-dict-django": "^1.0.4", - "cspell-dict-elixir": "^1.0.1", - "cspell-dict-en-gb": "^1.1.2", - "cspell-dict-en_us": "^1.2.5", - "cspell-dict-golang": "^1.1.3", - "cspell-dict-java": "^1.0.3", - "cspell-dict-latex": "^1.0.1", - "cspell-dict-lorem-ipsum": "^1.0.1", - "cspell-dict-php": "^1.0.2", - "cspell-dict-python": "^1.0.3", - "cspell-dict-rust": "^1.0.0", - "cspell-dict-scala": "^1.0.3", - "cspell-lib": "^3.0.2", - "cspell-trie": "^3.0.4", - "fs-extra": "^5.0.0", - "gensequence": "^2.1.1", - "glob": "^7.1.2", + "configstore": "^4.0.0", + "cspell-dict-companies": "^1.0.3", + "cspell-dict-cpp": "^1.1.11", + "cspell-dict-django": "^1.0.7", + "cspell-dict-elixir": "^1.0.4", + "cspell-dict-en-gb": "^1.1.7", + "cspell-dict-en_us": "^1.2.10", + "cspell-dict-fullstack": "^1.0.6", + "cspell-dict-golang": "^1.1.8", + "cspell-dict-java": "^1.0.5", + "cspell-dict-latex": "^1.0.6", + "cspell-dict-lorem-ipsum": "^1.0.4", + "cspell-dict-php": "^1.0.7", + "cspell-dict-python": "^1.0.8", + "cspell-dict-rust": "^1.0.6", + "cspell-dict-scala": "^1.0.5", + "cspell-lib": "^3.0.5", + "cspell-trie": "^3.0.7", + "fs-extra": "^7.0.1", + "gensequence": "^2.1.2", + "glob": "^7.1.3", "minimatch": "^3.0.4", - "rxjs": "^6.2.1", - "vscode-uri": "^1.0.5", - "xregexp": "^4.2.0" + "rxjs": "6.3.3", + "vscode-uri": "^1.0.6", + "xregexp": "^4.2.4" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "xregexp": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.2.4.tgz", + "integrity": "sha512-sO0bYdYeJAJBcJA8g7MJJX7UrOZIfJPd8U2SC7B2Dd/J24U0aQNoGp33shCaBSWeb0rD5rh6VBUIXOkGal1TZA==", + "dev": true, + "requires": { + "@babel/runtime-corejs2": "^7.2.0" + } + } + } + }, + "cspell-dict-companies": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cspell-dict-companies/-/cspell-dict-companies-1.0.3.tgz", + "integrity": "sha512-L4CKmMuI2kSno99tKYHI807y02niwxaFZOsRtmTjb0+zJ8dzyscXvQFmTwynUn3XZf4G+TbYcCOZaSpsx0RlWA==", + "dev": true, + "requires": { + "configstore": "^4.0.0" } }, "cspell-dict-cpp": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/cspell-dict-cpp/-/cspell-dict-cpp-1.1.8.tgz", - "integrity": "sha512-l6/Lc0bCauWuMm/kxjOfS39QuMi8wDIU9c3xeCbbWGNc9rV81VeHRZpCkp+CIfjtTAfIcrn3ZJNzL41oMxTArQ==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/cspell-dict-cpp/-/cspell-dict-cpp-1.1.11.tgz", + "integrity": "sha512-FWiOe6nntT1k4r/CkSo8qG6Ib4phu3WXGPqg6txOw+e9wlojzXN7rND2Z8AHt4TUA36h3lHpk/y7gTBgJgR+lw==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-django": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cspell-dict-django/-/cspell-dict-django-1.0.4.tgz", - "integrity": "sha512-UhD1fzgKOLGXZRRB+WjNwqLtWutcXJD1kHzT5ZC3IS613rPlWeK0N4q790Y9IjVk2S1sh3VYcJ/gStHS/CTLqA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cspell-dict-django/-/cspell-dict-django-1.0.7.tgz", + "integrity": "sha512-Gi7fYuGLEJSH307ywkOIziQYS3hdIBwMesjvEW71ovqjg0CyQKADcU4ZUd5fcMlndxRLpVhG4NXo3tGdsDf3wA==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-elixir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cspell-dict-elixir/-/cspell-dict-elixir-1.0.1.tgz", - "integrity": "sha512-/u9mEmfDZE/LkyrHRUeSy/bdXALeFE8Hwe8cMiVR3P1etJoVog8E8hp3JfkjEzwgIv/c9We9tv9UW5bMlWazGQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cspell-dict-elixir/-/cspell-dict-elixir-1.0.4.tgz", + "integrity": "sha512-K4W3kmb7ZLbtaoV0Xwd1XGS6DzNah3tygbp7yT4jaq2f6WvG8Uh80tSNog6YIF+DAVk6709RKbIurbHZsx08dg==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-en-gb": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cspell-dict-en-gb/-/cspell-dict-en-gb-1.1.2.tgz", - "integrity": "sha512-ry4yNIzjVMZDwSrK7U/0M9vXdbzo7ZFpUHUAYa4r6B4CwUFHBC/d8C0fcav2Hf1jjfQ866AApg00HiRJLP3Aug==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/cspell-dict-en-gb/-/cspell-dict-en-gb-1.1.7.tgz", + "integrity": "sha512-inEzvckvzzscmRE3zCF3dAtAdSD0xHeIba/KAFuu6/yVNWp0zwqMiW1UQ6lW6kXyueETjHLuZMSAJbC4R1DrOA==", "dev": true, "requires": { - "configstore": "^3.1.1" + "configstore": "^4.0.0" } }, "cspell-dict-en_us": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/cspell-dict-en_us/-/cspell-dict-en_us-1.2.5.tgz", - "integrity": "sha512-OaoOaVzIGxJeeyAjZE6Re2+S5OuLHsMFzQcZ3qaD87uO0Q7U9TF6EFPJEmwNuR0Ye9o1rXYYMiFKan6EzH40qg==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/cspell-dict-en_us/-/cspell-dict-en_us-1.2.10.tgz", + "integrity": "sha512-3unRvF++r1v2kh9C6R6jzIL0J67i8XIQ/RwNWjQ8fRBdchAzpiV9l0hnpXn4V98Icyy3r1aUpVzBIwGogBQiqw==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" + } + }, + "cspell-dict-fullstack": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cspell-dict-fullstack/-/cspell-dict-fullstack-1.0.6.tgz", + "integrity": "sha512-40rQ/6E5erZC4ZS7uQ8Q93M0VrFuqFhcGCup/ZrO2lRHsRPj5+iVeX80VY1jl/gPmG2H/pnJ5+oC5CJkgEBGVw==", + "dev": true, + "requires": { + "configstore": "^4.0.0" } }, "cspell-dict-golang": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/cspell-dict-golang/-/cspell-dict-golang-1.1.3.tgz", - "integrity": "sha512-maImSmm4ctZ5cQ3tFyZr5nglBQ/GwY5OYT1eq6O6USjJRQxzWtzmI1EV8WKng1UEA1i07NqgUDQLejTx3W1hIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/cspell-dict-golang/-/cspell-dict-golang-1.1.8.tgz", + "integrity": "sha512-Ux7Qm9P9sWiVHgbsuKQGJWj+iJkcQkLrlKmqsmNxXc9JeGpS6exmhJLNkhTjQwryB+ry5zcsvvobpCGUC+NBPw==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-java": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cspell-dict-java/-/cspell-dict-java-1.0.3.tgz", - "integrity": "sha512-0ZIvoXco3DczG0LSJMWYDCYESjBU9JNPSaVetKwKymQ2TrYi6vk5N18B5TNNRVlRh6hv2hw4DtDB6sz+TyP/yw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/cspell-dict-java/-/cspell-dict-java-1.0.5.tgz", + "integrity": "sha512-kwp3i+JW2LwzYFk0w9cPCGKe80z7V89GOubFTGpudm9E6y46eO+3YAAjVK5PhMIuuDYF69CicaiP6eW8FsbyhA==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-latex": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cspell-dict-latex/-/cspell-dict-latex-1.0.1.tgz", - "integrity": "sha512-RyK6TgEpt6AfGbXStPi5G7Fy2CFJGmIAYs1ie6Qsyss7h3sAsHk19F2yZvwJU0dlHXyw4LujFbzo9ZR3HR7BIA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cspell-dict-latex/-/cspell-dict-latex-1.0.6.tgz", + "integrity": "sha512-BQJbH1RwOPuIHfKsWKSBxIj2QZydVWPSRruwrMQ15gzcheYBz623QhedvrNMgm29AVoH7Lu7i0GIopOyb4ebPw==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-lorem-ipsum": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cspell-dict-lorem-ipsum/-/cspell-dict-lorem-ipsum-1.0.1.tgz", - "integrity": "sha512-r9O2rD1KQN8URw9sAecXfcAAYyt4xr7OpCXHp4ps/Iw9xH/X6eNxigRtOiv7Xl9NhyX9nPDeD9y3RgVsvSr2kQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cspell-dict-lorem-ipsum/-/cspell-dict-lorem-ipsum-1.0.4.tgz", + "integrity": "sha512-JcYUh671h4eLQ3ZX11fnf9pwcGNdFmuSBSE0T37UMFRWkhTPYzoAqXuoWQ1JPE4r4uq9KIEBzGl/VPOIpw1g7w==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-php": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cspell-dict-php/-/cspell-dict-php-1.0.2.tgz", - "integrity": "sha512-F2NyT9rZ6CmcLhbeGH8OKwLlD9Q5zQConpNDVdu/E/ucEQ+HXIf65Ou5KJzlQcyUGC8P9PUmmUBEF60oW5HcCA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cspell-dict-php/-/cspell-dict-php-1.0.7.tgz", + "integrity": "sha512-D17wWNAAnlzqSzN9xo7tqPlxyXebKKNXaBFpsehyTZy9GBBk4jzCk6tYW6QKPmAm/Z6rATRdaeoRg2u866+87A==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-python": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cspell-dict-python/-/cspell-dict-python-1.0.3.tgz", - "integrity": "sha512-zQYJu/kWvsZusuMelRk7e9B5xINglh49uLswLv598T+ZptzRzKO83im/yCG0RHBWvgYS+ze0eCpr0Ja5uqHu3Q==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/cspell-dict-python/-/cspell-dict-python-1.0.8.tgz", + "integrity": "sha512-j89SutsSPefWxjk8UjYVNEEIaFS07ubh2qXCGQyjMe8nKer2244QBrbUtCCDGeePEIOqvSNP1IS26k32a6SEuw==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-rust": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cspell-dict-rust/-/cspell-dict-rust-1.0.0.tgz", - "integrity": "sha512-9Rew1ad6yPXQW9fxFQ/J41+fbKg6t9p4oSm7JS0aHuCtWc3w0knFYK7Ty/mVMw6oDFlemBNaBCPZON0M3+oIKg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cspell-dict-rust/-/cspell-dict-rust-1.0.6.tgz", + "integrity": "sha512-dOBSzOwV+HkfLqMq7JKNaxjUa3W0szWa2gKslZMvolwdaV5t2yWion0EfO63JvFZqky/oN2on52CQ3wSgHlT3w==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-dict-scala": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cspell-dict-scala/-/cspell-dict-scala-1.0.3.tgz", - "integrity": "sha512-kYcnQcLk042pTn9EGyOEM9bZXZ/6NAnGKb/IhRJiF2+iStHm5u1jBMeTuHqiU4hOPDbVcE6lK6pZv7lDYQPNZA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/cspell-dict-scala/-/cspell-dict-scala-1.0.5.tgz", + "integrity": "sha512-7rAmPo36imNIb6X9wu02SCaF5hW8d6/ECPDixFD/X+yyHNGnZDOKlx1eVd4jDEHbL+m0v6CdHBxM2te8nnfgdA==", "dev": true, "requires": { - "configstore": "^3.1.0" + "configstore": "^4.0.0" } }, "cspell-lib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-3.0.2.tgz", - "integrity": "sha512-a6T8qlqnFz40C36Rl/jfu72ev6YyHlN9cwSR0uDwKADl+BOfbvfEPpx9neUB3jYYwIafa3S5BRict7erD/H2EQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-3.0.5.tgz", + "integrity": "sha512-z2f5t4un43qWFYYtEKjdDj1aG2TIdOUUYQpytkDrzWcJxyOkSzxOPItOe9zypQeJrIQ8YeVnrazzKpzeap/Ulw==", "dev": true, "requires": { - "iconv-lite": "^0.4.22", - "rxjs-stream": "^2.0.3" + "iconv-lite": "^0.4.24", + "rxjs-stream": "^3.0.1" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } } }, "cspell-trie": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/cspell-trie/-/cspell-trie-3.0.4.tgz", - "integrity": "sha512-dCc8YX54C4pfGcQDV/XpK4AcPfEME6Io+LATvLi0HHmkebuSTzOcal58TgbFXeL6+06s7zqID9K3Oq/wcmEwrw==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/cspell-trie/-/cspell-trie-3.0.7.tgz", + "integrity": "sha512-ASunLF5cb9qr8aLw23mcD6150Ipcn3c2pGcbIgN6Qoenk12An3JYZIi9+SLDvsf/LgPFa+EccUiFw1ox+WpvKg==", "dev": true, "requires": { - "commander": "^2.15.1", - "cspell-lib": "^3.0.2", - "fs-extra": "^5.0.0", + "commander": "^2.18.0", + "cspell-lib": "^3.0.4", + "fs-extra": "^7.0.0", "gensequence": "^2.1.1", - "hunspell-reader": "^2.0.2", - "rxjs": "^6.1.0", - "rxjs-stream": "^2.0.3" + "hunspell-reader": "^2.0.3", + "rxjs": "^6.3.3", + "rxjs-stream": "^3.0.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + } } }, "css-parse": { @@ -5048,16 +3678,14 @@ "dev": true, "requires": { "assert-plus": "^1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, "date-format": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", @@ -5071,11 +3699,11 @@ "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "decamelize": { @@ -5090,6 +3718,12 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", @@ -5097,55 +3731,19 @@ "dev": true }, "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "default-gateway": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz", - "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==", - "dev": true, - "requires": { - "execa": "^0.10.0", - "ip-regex": "^2.1.0" - }, - "dependencies": { - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - } + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "default-gateway": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-2.7.2.tgz", + "integrity": "sha512-lAc4i9QJR0YHSDFdzeBQKfZ1SRDG3hsJNEkrpcZa8QhBfidLAilT60BDEIVUUGqosFp425KOgB3uYqcnQrWafQ==", + "dev": true, + "requires": { + "execa": "^0.10.0", + "ip-regex": "^2.1.0" } }, "default-require-extensions": { @@ -5203,18 +3801,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -5234,7 +3820,7 @@ "dependencies": { "globby": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", "dev": true, "requires": { @@ -5247,7 +3833,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -5323,7 +3909,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { @@ -5333,12 +3919,11 @@ } }, "dir-glob": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", - "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", "dev": true, "requires": { - "arrify": "^1.0.1", "path-type": "^3.0.0" } }, @@ -5401,9 +3986,9 @@ "dev": true }, "duplexify": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, "requires": { "end-of-stream": "^1.0.0", @@ -5417,7 +4002,6 @@ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", "dev": true, - "optional": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.1.0" @@ -5429,6 +4013,18 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", "dev": true }, + "electron-to-chromium": { + "version": "1.3.113", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.113.tgz", + "integrity": "sha512-De+lPAxEcpxvqPTyZAXELNpRZXABRxf+uL/rSykstQhzj/B0l1150G/ExIIxKc16lI89Hgz81J0BHAcbTqK49g==", + "dev": true + }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", + "dev": true + }, "elliptic": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", @@ -5474,9 +4070,9 @@ } }, "engine.io": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.0.tgz", - "integrity": "sha512-mRbgmAtQ4GAlKwuPnnAvXXwdPhEx+jkc0OBCLrXuD/CRvwNK3AxRSnqK4FSqmAMRRHryVJP8TopOvmEaA64fKw==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", "dev": true, "requires": { "accepts": "~1.3.4", @@ -5485,11 +4081,28 @@ "debug": "~3.1.0", "engine.io-parser": "~2.1.0", "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "engine.io-client": { "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", "dev": true, "requires": { @@ -5504,18 +4117,35 @@ "ws": "~3.3.1", "xmlhttprequest-ssl": "~1.5.4", "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", "dev": true, "requires": { "after": "0.8.2", "arraybuffer.slice": "~0.0.7", "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", + "blob": "0.0.5", "has-binary2": "~1.0.2" } }, @@ -5561,9 +4191,9 @@ } }, "es5-ext": { - "version": "0.10.45", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", - "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", + "version": "0.10.47", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.47.tgz", + "integrity": "sha512-/1TItLfj+TTfWoeRcDn/0FbGV6SNo4R+On2GGVucPU/j3BWnXE2Co8h8CTo4Tu34gFJtnmwS9xiScKs4EjZhdw==", "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", @@ -5591,14 +4221,14 @@ } }, "es6-promise": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz", - "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.5.tgz", + "integrity": "sha512-n6wvpdE43VFtJq+lUDYDBFUwV8TZbuGXLV4D6wKafg13ldznKsyEvatubnmUe31zcvelSzOHF+XbaT+Bl9ObDg==", "dev": true }, "es6-promisify": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", "dev": true, "requires": { @@ -5636,31 +4266,6 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, - "dependencies": { - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, "eslint-scope": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", @@ -5669,14 +4274,6 @@ "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } } }, "esprima": { @@ -5709,20 +4306,12 @@ "dev": true, "requires": { "estraverse": "^4.1.0" - }, - "dependencies": { - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - } } }, "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", "dev": true }, "estree-walker": { @@ -5759,9 +4348,9 @@ "dev": true }, "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", + "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", "dev": true }, "eventsource": { @@ -5784,12 +4373,12 @@ } }, "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", + "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", "dev": true, "requires": { - "cross-spawn": "^5.0.1", + "cross-spawn": "^6.0.0", "get-stream": "^3.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", @@ -5799,12 +4388,14 @@ }, "dependencies": { "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "lru-cache": "^4.0.1", + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } @@ -5828,6 +4419,12 @@ "braces": "^0.1.2" }, "dependencies": { + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, "braces": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", @@ -5839,7 +4436,7 @@ }, "expand-range": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { @@ -5862,21 +4459,104 @@ } }, "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "expand-range": { "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { "fill-range": "^2.1.0" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "express": { @@ -5919,28 +4599,10 @@ "dependencies": { "array-flatten": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", "dev": true }, - "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", - "dev": true, - "requires": { - "bytes": "3.0.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", - "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -5950,17 +4612,17 @@ "ms": "2.0.0" } }, - "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", - "dev": true, - "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", - "unpipe": "1.0.0" - } + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true } } }, @@ -6013,12 +4675,68 @@ } }, "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } } }, "extsprintf": { @@ -6037,12 +4755,6 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, "fastparse": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", @@ -6074,9 +4786,9 @@ } }, "file-loader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-2.0.0.tgz", - "integrity": "sha512-YCsBfd1ZGCyonOKLxPiKPdu+8ld9HAaMEvJewzz+b2eTF7uL5Zm/HdBF6FjCrpCMRq25Mi0U1gl4pwn2TlH7hQ==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", "dev": true, "requires": { "loader-utils": "^1.0.2", @@ -6113,21 +4825,31 @@ } }, "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "finalhandler": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "dev": true, "requires": { @@ -6148,6 +4870,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -6177,23 +4905,65 @@ "locate-path": "^2.0.0" } }, + "flatted": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz", + "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==", + "dev": true + }, "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.0.tgz", + "integrity": "sha512-6MHED/cmsyux1G4/Cek2Z776y9t7WCNd3h2h/HW91vFeU7pzMhA8XvAlDhHcanG5IWuIh/xcC7JASY4WQpG6xg==", "dev": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } } }, + "fn-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz", + "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=", + "dev": true + }, "follow-redirects": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.2.tgz", - "integrity": "sha512-kssLorP/9acIdpQ2udQVTiCS5LQmdEz9mvdIfDcl1gYX2tPKFADHSyFdvJS040XdFsPzemWtgI3q8mFVCxtX8A==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz", + "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==", "dev": true, "requires": { - "debug": "^3.1.0" + "debug": "=3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "for-in": { @@ -6203,9 +4973,9 @@ "dev": true }, "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { "for-in": "^1.0.1" @@ -6218,12 +4988,12 @@ "dev": true }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", "requires": { "asynckit": "^0.4.0", - "combined-stream": "1.0.6", + "combined-stream": "^1.0.6", "mime-types": "^2.1.12" } }, @@ -6265,7 +5035,7 @@ }, "fs-access": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", "dev": true, "requires": { @@ -6273,9 +5043,9 @@ } }, "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -6311,9 +5081,9 @@ "dev": true }, "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.7.tgz", + "integrity": "sha512-Pxm6sI2MeBD7RdD12RYsqaP0nMiwx8eZBXCa6z2L+mRHm2DYrOYwihmhjpkdjUHwQhslWQjRpEgNq4XvBmaAuw==", "dev": true, "optional": true, "requires": { @@ -6323,28 +5093,25 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "version": "1.1.5", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6354,56 +5121,53 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "version": "1.1.1", + "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "dev": true, "optional": true }, "debug": { "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6411,30 +5175,26 @@ } }, "deep-extend": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", - "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", + "version": "0.6.0", + "bundled": true, "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, "dev": true, "optional": true }, "fs-minipass": { "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6443,15 +5203,13 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6466,9 +5224,8 @@ } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6482,25 +5239,22 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true, "optional": true }, "iconv-lite": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", - "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "version": "0.4.24", + "bundled": true, "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": ">= 2.1.2 < 3" } }, "ignore-walk": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6509,8 +5263,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6520,62 +5273,59 @@ }, "inherits": { "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "bundled": true, "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "minipass": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", - "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", + "version": "2.3.5", + "bundled": true, "dev": true, + "optional": true, "requires": { - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "version": "1.2.1", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6584,24 +5334,22 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } }, "ms": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "bundled": true, "dev": true, "optional": true }, "needle": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", - "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", + "version": "2.2.4", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6611,19 +5359,18 @@ } }, "node-pre-gyp": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", - "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", + "version": "0.10.3", + "bundled": true, "dev": true, "optional": true, "requires": { "detect-libc": "^1.0.2", "mkdirp": "^0.5.1", - "needle": "^2.2.0", + "needle": "^2.2.1", "nopt": "^4.0.1", "npm-packlist": "^1.1.6", "npmlog": "^4.0.2", - "rc": "^1.1.7", + "rc": "^1.2.7", "rimraf": "^2.6.1", "semver": "^5.3.0", "tar": "^4" @@ -6631,8 +5378,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6641,16 +5387,14 @@ } }, "npm-bundled": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", - "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "version": "1.0.5", + "bundled": true, "dev": true, "optional": true }, "npm-packlist": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", - "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "version": "1.2.0", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6660,8 +5404,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6673,44 +5416,40 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "bundled": true, "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6720,26 +5459,23 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "bundled": true, "dev": true, "optional": true }, "rc": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", - "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "version": "1.2.8", + "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", + "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" @@ -6747,8 +5483,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "bundled": true, "dev": true, "optional": true } @@ -6756,8 +5491,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6771,61 +5505,55 @@ } }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.6.3", + "bundled": true, "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true + "version": "5.1.2", + "bundled": true, + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, "dev": true, "optional": true }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "5.6.0", + "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6834,8 +5562,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -6844,64 +5571,60 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "bundled": true, "dev": true, "optional": true }, "tar": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", - "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "version": "4.4.8", + "bundled": true, "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", + "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", + "minipass": "^2.3.4", + "minizlib": "^1.1.1", "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.2" } }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "dev": true, "optional": true }, "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "version": "1.1.3", + "bundled": true, "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "^1.0.2 || 2" } }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "bundled": true, + "dev": true, + "optional": true }, "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", - "dev": true + "version": "3.0.3", + "bundled": true, + "dev": true, + "optional": true } } }, @@ -6917,6 +5640,17 @@ "rimraf": "2" } }, + "g-status": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz", + "integrity": "sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "matcher": "^1.0.0", + "simple-git": "^1.85.0" + } + }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", @@ -6949,9 +5683,9 @@ "dev": true }, "gensequence": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-2.1.1.tgz", - "integrity": "sha512-AyZrG5Qq8Tn0qnaDCnH2n9TsWnJLKBXEa2FcUlHWfEgl1rRS3MbcvB4OsarxyEekx/PwYlyKXvjQwNvYsByXAw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-2.1.2.tgz", + "integrity": "sha512-TH0HcxnR7gpvpdMbiQ7+mL10Vf+9zekenuaSmUl7dHWzzeiiaCelk3Xv3V2ebrsVMLfi1KJ8Q0CpGthaxiM9zQ==", "dev": true }, "get-caller-file": { @@ -6960,6 +5694,12 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-own-enumerable-property-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz", + "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==", + "dev": true + }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -6968,7 +5708,7 @@ }, "get-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, @@ -6985,20 +5725,12 @@ "dev": true, "requires": { "assert-plus": "^1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -7017,15 +5749,53 @@ "requires": { "glob-parent": "^2.0.0", "is-glob": "^2.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } } }, "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "^2.0.0" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } } }, "global-dirs": { @@ -7070,7 +5840,7 @@ }, "got": { "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "resolved": "http://registry.npmjs.org/got/-/got-6.7.1.tgz", "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", "dev": true, "requires": { @@ -7081,111 +5851,29 @@ "is-retry-allowed": "^1.0.0", "is-stream": "^1.0.0", "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "hammerjs": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", - "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" - }, - "handle-thing": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", - "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", - "dev": true - }, - "handlebars": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", - "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", - "dev": true, - "requires": { - "async": "^1.4.0", - "optimist": "^0.6.1", - "source-map": "^0.4.4", - "uglify-js": "^2.6" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true, - "optional": true - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "optional": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", - "dev": true, - "optional": true, - "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true - } - } - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "optional": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - } - } + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "unzip-response": "^2.0.1", + "url-parse-lax": "^1.0.0" } }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "hammerjs": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", + "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" + }, + "handle-thing": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", + "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", + "dev": true + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -7193,39 +5881,13 @@ "dev": true }, "har-validator": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", - "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "dev": true, "requires": { - "ajv": "^5.1.0", + "ajv": "^6.5.5", "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - } } }, "has-ansi": { @@ -7281,14 +5943,6 @@ "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "has-values": { @@ -7301,26 +5955,6 @@ "kind-of": "^4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -7343,9 +5977,9 @@ } }, "hash.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", - "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -7394,377 +6028,94 @@ "obuf": "^1.0.0", "readable-stream": "^2.0.1", "wbuf": "^1.1.0" - } - }, - "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", - "dev": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "http-parser-js": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", - "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", - "dev": true - }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "http-proxy-middleware": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", - "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", - "dev": true, - "requires": { - "http-proxy": "^1.16.2", - "is-glob": "^4.0.0", - "lodash": "^4.17.5", - "micromatch": "^3.1.9" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + } + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-parser-js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz", + "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==", + "dev": true + }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "dev": true, + "requires": { + "eventemitter3": "^3.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", + "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "dev": true, + "requires": { + "agent-base": "4", + "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "ms": "2.0.0" } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } } } }, + "http-proxy-middleware": { + "version": "0.18.0", + "resolved": "http://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.18.0.tgz", + "integrity": "sha512-Fs25KVMPAIIcgjMZkVHJoKg9VcXcC1C8yb9JUgeDvVXY0S/zgVIhMb+qVswDIgtJe2DfckMSY2d6TuTEutlk6Q==", + "dev": true, + "requires": { + "http-proxy": "^1.16.2", + "is-glob": "^4.0.0", + "lodash": "^4.17.5", + "micromatch": "^3.1.9" + } + }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -7802,17 +6153,25 @@ } }, "hunspell-reader": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hunspell-reader/-/hunspell-reader-2.0.3.tgz", - "integrity": "sha512-TYztrMmCOuz/HI2BluZBprWvfqCcQXNErj2ZqJjR/zGWkXkhVwqgcdiW7T8HCHnGQDlV3RuuRlkRcfyo0W9kdQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/hunspell-reader/-/hunspell-reader-2.1.2.tgz", + "integrity": "sha512-RuaK4dpY1iUIazNxQcqSA5d5B0vcih0JPsb2X87nwxjqWSlM5fnckSVC9vLYrKddF/PL53fH9nQOqoHKvFndxg==", "dev": true, "requires": { - "commander": "^2.15.1", - "cspell-lib": "^3.0.2", - "fs-extra": "^5.0.0", - "gensequence": "^2.1.1", - "rxjs": "^6.2.0", - "rxjs-stream": "^2.0.3" + "commander": "^2.19.0", + "cspell-lib": "^3.0.5", + "fs-extra": "^7.0.1", + "gensequence": "^2.1.2", + "rxjs": "^6.3.3", + "rxjs-stream": "^3.0.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + } } }, "iconv-lite": { @@ -7873,6 +6232,16 @@ "import-from": "^2.1.0" } }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, "import-from": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", @@ -7918,9 +6287,9 @@ } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -8007,9 +6376,9 @@ "dev": true }, "inquirer": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", - "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.1.tgz", + "integrity": "sha512-088kl3DRT2dLU5riVMKKr1DlImd6X7smDhpXUCkJDCKvTEJeRiXh0G132HG9u5a+6Ylw9plFRY7RuTnwohYSpg==", "dev": true, "requires": { "ansi-escapes": "^3.0.0", @@ -8023,7 +6392,7 @@ "run-async": "^2.2.0", "rxjs": "^6.1.0", "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", + "strip-ansi": "^5.0.0", "through": "^2.3.6" }, "dependencies": { @@ -8047,15 +6416,34 @@ "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.0.0.tgz", + "integrity": "sha512-Uu7gQyZI7J7gn5qLn1Np3G9vcYGTVqB+lFTytnDJv83dd8T22aGH451P3jueT2/QemInJDfxHB5Tde5OzgG1Ow==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.0.0.tgz", + "integrity": "sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w==", + "dev": true + } } } } @@ -8071,9 +6459,9 @@ } }, "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", + "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, "invariant": { @@ -8111,11 +6499,22 @@ }, "is-accessor-descriptor": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-arrayish": { @@ -8141,7 +6540,7 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { @@ -8159,11 +6558,22 @@ }, "is-data-descriptor": { "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-descriptor": { @@ -8213,9 +6623,9 @@ "dev": true }, "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-finite": { @@ -8237,12 +6647,12 @@ } }, "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "^2.1.1" } }, "is-installed-globally": { @@ -8268,20 +6678,40 @@ "dev": true }, "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-obj": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "dev": true, + "requires": { + "symbol-observable": "^1.1.0" + } + }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -8313,14 +6743,6 @@ "dev": true, "requires": { "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "is-posix-bracket": { @@ -8347,6 +6769,12 @@ "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", "dev": true }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-retry-allowed": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", @@ -8398,9 +6826,9 @@ } }, "isemail": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.1.3.tgz", - "integrity": "sha512-5xbsG5wYADIcB+mfLsd+nst1V/D+I7EU7LEZPo2GOIMu4JzfcRs5yQoypP4avA7QtUqgxYLKBYNv4IdzBmbhdw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", "dev": true, "requires": { "punycode": "2.x.x" @@ -8413,13 +6841,10 @@ "dev": true }, "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -8427,96 +6852,59 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, - "istanbul": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-0.4.5.tgz", - "integrity": "sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs=", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" + "istanbul-api": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-2.1.1.tgz", + "integrity": "sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw==", + "dev": true, + "requires": { + "async": "^2.6.1", + "compare-versions": "^3.2.1", + "fileset": "^2.0.3", + "istanbul-lib-coverage": "^2.0.3", + "istanbul-lib-hook": "^2.0.3", + "istanbul-lib-instrument": "^3.1.0", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.2", + "istanbul-reports": "^2.1.1", + "js-yaml": "^3.12.0", + "make-dir": "^1.3.0", + "minimatch": "^3.0.4", + "once": "^1.4.0" }, "dependencies": { "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "lodash": "^4.17.11" } }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", "dev": true }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "istanbul-lib-instrument": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz", + "integrity": "sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "istanbul-lib-coverage": "^2.0.3", + "semver": "^5.5.0" } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true } } }, - "istanbul-api": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.1.tgz", - "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", - "dev": true, - "requires": { - "async": "^2.1.4", - "compare-versions": "^3.1.0", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.0", - "istanbul-lib-hook": "^1.2.0", - "istanbul-lib-instrument": "^1.10.1", - "istanbul-lib-report": "^1.1.4", - "istanbul-lib-source-maps": "^1.2.4", - "istanbul-reports": "^1.3.0", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" - } - }, "istanbul-instrumenter-loader": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", @@ -8543,7 +6931,7 @@ }, "fast-deep-equal": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", "dev": true }, @@ -8565,24 +6953,24 @@ } }, "istanbul-lib-coverage": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.0.tgz", - "integrity": "sha512-GvgM/uXRwm+gLlvkWHTjDAvwynZkL9ns15calTrmhGgowlwJBbWMYzWbKqE2DT6JDP1AFXKa+Zi0EkqNCUqY0A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", "dev": true }, "istanbul-lib-hook": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.1.tgz", - "integrity": "sha512-eLAMkPG9FU0v5L02lIkcj/2/Zlz9OuluaXikdr5iStk8FDbSwAixTK9TkYxbF0eNnzAJTwM2fkV2A1tpsIp4Jg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz", + "integrity": "sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA==", "dev": true, "requires": { "append-transform": "^1.0.0" } }, "istanbul-lib-instrument": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", - "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", "dev": true, "requires": { "babel-generator": "^6.18.0", @@ -8590,59 +6978,101 @@ "babel-traverse": "^6.18.0", "babel-types": "^6.18.0", "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.0", + "istanbul-lib-coverage": "^1.2.1", "semver": "^5.3.0" } }, "istanbul-lib-report": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.4.tgz", - "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz", + "integrity": "sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA==", "dev": true, "requires": { - "istanbul-lib-coverage": "^1.2.0", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "supports-color": "^6.0.0" }, "dependencies": { - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } } } }, "istanbul-lib-source-maps": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.5.tgz", - "integrity": "sha512-8O2T/3VhrQHn0XcJbP1/GN7kXMiRAlPi+fj3uEHrjBD8Oz7Py0prSC25C09NuAZS6bgW1NNKAvCSHZXB0irSGA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz", + "integrity": "sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ==", "dev": true, "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.0", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.3", + "make-dir": "^1.3.0", + "rimraf": "^2.6.2", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "istanbul-lib-coverage": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "istanbul-reports": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.3.0.tgz", - "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.1.1.tgz", + "integrity": "sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw==", "dev": true, "requires": { - "handlebars": "^4.0.3" + "handlebars": "^4.1.0" + }, + "dependencies": { + "async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", + "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", + "dev": true, + "requires": { + "lodash": "^4.17.11" + } + }, + "handlebars": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.0.tgz", + "integrity": "sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w==", + "dev": true, + "requires": { + "async": "^2.5.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "jasmine": { @@ -8681,41 +7111,6 @@ "colors": "1.1.2" } }, - "jasmine2-protractor-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jasmine2-protractor-utils/-/jasmine2-protractor-utils-1.3.0.tgz", - "integrity": "sha1-lARqq7x0rQpLdGvNTcMFB1h7Z+M=", - "dev": true, - "requires": { - "fs-extra": "^0.26.5", - "mkdirp": "^0.5.1", - "q": "^1.4.1" - }, - "dependencies": { - "fs-extra": { - "version": "0.26.7", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", - "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, - "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - } - } - }, "jasminewd2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/jasminewd2/-/jasminewd2-2.2.0.tgz", @@ -8723,9 +7118,9 @@ "dev": true }, "joi": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-13.6.0.tgz", - "integrity": "sha512-E4QB0yRgEa6ZZKcSHJuBC+QeAwy+akCG0Bsa9edLqljyhlr+GuGDSmXYW1q7sj/FuAPy+ECUI3evVtK52tVfwg==", + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-13.7.0.tgz", + "integrity": "sha512-xuY5VkHfeOYK3Hdi91ulocfuFopwgbSORmIwzcwHKESQhC7w1kD5jaVSPnqDxS2I8t3RZ9omCKAxNwXN5zG1/Q==", "dev": true, "requires": { "hoek": "5.x.x", @@ -8734,9 +7129,9 @@ } }, "js-base64": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.8.tgz", - "integrity": "sha512-hm2nYpDrwoO/OzBhdcqs/XGT6XjSuSSCVEpia+Kl2J6x4CYt5hISlVL/AYU1khoDXv0AQVgxtdJySb9gjAn56Q==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz", + "integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==", "dev": true }, "js-tokens": { @@ -8746,9 +7141,9 @@ "dev": true }, "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -8767,12 +7162,11 @@ "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true + "dev": true }, "jsesc": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", "dev": true }, @@ -8815,9 +7209,12 @@ "dev": true }, "json5": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", - "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } }, "jsonfile": { "version": "4.0.0", @@ -8844,14 +7241,6 @@ "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } } }, "jszip": { @@ -8869,13 +7258,13 @@ "dependencies": { "core-js": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", "integrity": "sha1-+rg/uwstjchfpjbEudNMdUIMbWU=", "dev": true }, "es6-promise": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", + "resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=", "dev": true }, @@ -8887,7 +7276,7 @@ }, "readable-stream": { "version": "2.0.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", "dev": true, "requires": { @@ -8901,16 +7290,16 @@ }, "string_decoder": { "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true } } }, "karma": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-3.0.0.tgz", - "integrity": "sha512-ZTjyuDXVXhXsvJ1E4CnZzbCjSxD6sEdzEsFYogLuZM0yqvg/mgz+O+R1jb0J7uAQeuzdY8kJgx6hSNXLwFuHIQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.0.0.tgz", + "integrity": "sha512-EFoFs3F6G0BcUGPNOn/YloGOb3h09hzTguyXlg6loHlKY76qbJikkcyPk43m2kfRF65TUGda/mig29QQtyhm1g==", "dev": true, "requires": { "bluebird": "^3.3.0", @@ -8923,11 +7312,12 @@ "di": "^0.0.1", "dom-serialize": "^2.2.0", "expand-braces": "^0.1.1", + "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.4", + "lodash": "^4.17.5", "log4js": "^3.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", @@ -8939,363 +7329,13 @@ "socket.io": "2.1.1", "source-map": "^0.6.1", "tmp": "0.0.33", - "useragent": "2.2.1" + "useragent": "2.3.0" }, "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, "mime": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", - "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true }, "source-map": { @@ -9318,7 +7358,7 @@ }, "karma-cli": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/karma-cli/-/karma-cli-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/karma-cli/-/karma-cli-1.0.1.tgz", "integrity": "sha1-rmw8WKMTodALRRZMRVubhs4X+WA=", "dev": true, "requires": { @@ -9326,12 +7366,12 @@ } }, "karma-coverage-istanbul-reporter": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-1.4.3.tgz", - "integrity": "sha1-O13/RmT6W41RlrmInj9hwforgNk=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/karma-coverage-istanbul-reporter/-/karma-coverage-istanbul-reporter-2.0.4.tgz", + "integrity": "sha512-xJS7QSQIVU6VK9HuJ/ieE5yynxKhjCCkd96NLY/BX/HXsx0CskU9JJiMQbd4cHALiddMwI4OWh1IIzeWrsavJw==", "dev": true, "requires": { - "istanbul-api": "^1.3.1", + "istanbul-api": "^2.0.5", "minimatch": "^3.0.4" } }, @@ -9343,7 +7383,7 @@ }, "karma-jasmine-html-reporter": { "version": "0.2.2", - "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz", + "resolved": "http://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-0.2.2.tgz", "integrity": "sha1-SKjl7xiAdhfuK14zwRlMNbQ5Ukw=", "dev": true, "requires": { @@ -9357,24 +7397,6 @@ "dev": true, "requires": { "source-map-support": "^0.5.5" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - } } }, "killable": { @@ -9384,21 +7406,18 @@ "dev": true }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.9" + "graceful-fs": "^4.1.11" } }, "latest-version": { @@ -9408,14 +7427,7 @@ "dev": true, "requires": { "package-json": "^4.0.0" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true, - "optional": true + } }, "lcid": { "version": "1.0.0", @@ -9427,9 +7439,9 @@ } }, "less": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/less/-/less-3.8.1.tgz", - "integrity": "sha512-8HFGuWmL3FhQR0aH89escFNBQH/nEiYPP2ltDFdQw2chE28Yx2E3lhAIq9Y2saYwLSwa699s4dBVEfCY8Drf7Q==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/less/-/less-3.9.0.tgz", + "integrity": "sha512-31CmtPEZraNUtuUREYjSqRkeETFdyEHSEPAGq4erDlUXtda7pzNmctdljdIagSb589d/qXGWiiP31R5JVf+v0w==", "dev": true, "requires": { "clone": "^2.1.2", @@ -9475,37 +7487,22 @@ "dependencies": { "promise": { "version": "7.0.4", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.0.4.tgz", + "resolved": "http://registry.npmjs.org/promise/-/promise-7.0.4.tgz", "integrity": "sha1-Nj6EpMNsg1a4kP7WLJHOhdAu1Tk=", "dev": true, "requires": { "asap": "~2.0.3" } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true } } }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, "license-webpack-plugin": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.0.2.tgz", - "integrity": "sha512-GsomZw5VoT20ST8qH2tOjBgbyhn6Pgs9M94g0mbvfBIV1VXufm1iKY+4dbgfTObj1Mp6nSRE3Zf74deOZr0KwA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.0.tgz", + "integrity": "sha512-vDiBeMWxjE9n6TabQ9J4FH8urFdsRK0Nvxn1cit9biCiR9aq1zBR0X2BlAkEiIG6qPamLeU0GzvIgLkrFc398A==", "dev": true, "requires": { + "@types/webpack-sources": "^0.1.5", "webpack-sources": "^1.2.0" } }, @@ -9518,9 +7515,224 @@ "immediate": "~3.0.5" } }, + "lint-staged": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-8.1.4.tgz", + "integrity": "sha512-oFbbhB/VzN8B3i/sIdb9gMfngGArI6jIfxSn+WPdQb2Ni3GJeS6T4j5VriSbQfxfMuYoQlMHOoFt+lfcWV0HfA==", + "dev": true, + "requires": { + "@iamstarkov/listr-update-renderer": "0.4.1", + "chalk": "^2.3.1", + "commander": "^2.14.1", + "cosmiconfig": "^5.0.2", + "debug": "^3.1.0", + "dedent": "^0.7.0", + "del": "^3.0.0", + "execa": "^1.0.0", + "find-parent-dir": "^0.3.0", + "g-status": "^2.0.2", + "is-glob": "^4.0.0", + "is-windows": "^1.0.2", + "listr": "^0.14.2", + "lodash": "^4.17.11", + "log-symbols": "^2.2.0", + "micromatch": "^3.1.8", + "npm-which": "^3.0.1", + "p-map": "^1.1.1", + "path-is-inside": "^1.0.2", + "pify": "^3.0.0", + "please-upgrade-node": "^3.0.2", + "staged-git-files": "1.1.2", + "string-argv": "^0.0.2", + "stringify-object": "^3.2.2", + "yup": "^0.26.10" + }, + "dependencies": { + "cosmiconfig": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.0.7.tgz", + "integrity": "sha512-PcLqxTKiDmNT6pSpy4N6KtuPwb53W+2tzNvwOZw0WH9N6O0vLIBq0x8aj8Oj75ere4YcGi48bDFCL+3fRJdlNA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "listr": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", + "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", + "dev": true, + "requires": { + "@samverschueren/stream-to-observable": "^0.3.0", + "is-observable": "^1.1.0", + "is-promise": "^2.1.0", + "is-stream": "^1.1.0", + "listr-silent-renderer": "^1.1.1", + "listr-update-renderer": "^0.5.0", + "listr-verbose-renderer": "^0.5.0", + "p-map": "^2.0.0", + "rxjs": "^6.3.3" + }, + "dependencies": { + "p-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.0.0.tgz", + "integrity": "sha512-GO107XdrSUmtHxVoi60qc9tUl/KkNKm+X2CF4P9amalpGxv5YqVPJNfSb0wcA+syCopkZvYYIzW8OVTQW59x/w==", + "dev": true + } + } + }, + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=", + "dev": true + }, + "listr-update-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", + "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "cli-truncate": "^0.2.1", + "elegant-spinner": "^1.0.1", + "figures": "^1.7.0", + "indent-string": "^3.0.0", + "log-symbols": "^1.0.2", + "log-update": "^2.3.0", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "dev": true, + "requires": { + "chalk": "^1.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "listr-verbose-renderer": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", + "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cli-cursor": "^2.1.0", + "date-fns": "^1.27.2", + "figures": "^2.0.0" + } + }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { @@ -9533,26 +7745,26 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } }, "loader-runner": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", - "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", "dev": true }, "loader-utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", - "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "requires": { - "big.js": "^3.1.3", + "big.js": "^5.2.2", "emojis-list": "^2.0.0", - "json5": "^0.5.0" + "json5": "^1.0.1" } }, "locate-path": { @@ -9566,9 +7778,9 @@ } }, "lodash": { - "version": "4.17.10", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", - "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash.assign": { @@ -9601,10 +7813,73 @@ "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", "dev": true }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "log-update": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", + "integrity": "sha1-iDKP19HOeTiykoN0bwsbwSayRwg=", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "cli-cursor": "^2.0.0", + "wrap-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + } + } + } + }, "log4js": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.5.tgz", - "integrity": "sha512-IX5c3G/7fuTtdr0JjOT2OIR12aTESVhsH6cEsijloYwKgcPRlO6DgOU72v0UFhWcoV1HN6+M3dwT89qVPLXm0w==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", + "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", "dev": true, "requires": { "circular-json": "^0.5.5", @@ -9620,12 +7895,6 @@ "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", "dev": true }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, "loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -9652,9 +7921,9 @@ "dev": true }, "lru-cache": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", - "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -9662,12 +7931,12 @@ } }, "magic-string": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz", - "integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==", + "version": "0.25.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.2.tgz", + "integrity": "sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg==", "dev": true, "requires": { - "sourcemap-codec": "^1.4.1" + "sourcemap-codec": "^1.4.4" } }, "make-dir": { @@ -9680,9 +7949,9 @@ } }, "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", + "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", "dev": true }, "make-fetch-happen": { @@ -9705,25 +7974,36 @@ }, "dependencies": { "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + } } }, "mississippi": { @@ -9762,6 +8042,12 @@ "requires": { "figgy-pudding": "^3.5.1" } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true } } }, @@ -9795,10 +8081,19 @@ "object-visit": "^1.0.0" } }, + "matcher": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", + "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.4" + } + }, "math-random": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", "dev": true }, "md5.js": { @@ -9814,17 +8109,19 @@ }, "media-typer": { "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, "mem": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.1.0.tgz", + "integrity": "sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg==", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^2.0.0" } }, "memory-fs": { @@ -9839,7 +8136,7 @@ }, "meow": { "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { @@ -9853,14 +8150,6 @@ "read-pkg-up": "^1.0.1", "redent": "^1.0.0", "trim-newlines": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "merge-descriptors": { @@ -9875,24 +8164,24 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "miller-rabin": { @@ -9911,16 +8200,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.35.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.35.0.tgz", - "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" }, "mime-types": { - "version": "2.1.19", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz", - "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "requires": { - "mime-db": "~1.35.0" + "mime-db": "~1.37.0" } }, "mimic-fn": { @@ -9930,9 +8219,9 @@ "dev": true }, "mini-css-extract-plugin": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.4.tgz", - "integrity": "sha512-o+Jm+ocb0asEngdM6FsZWtZsRzA8koFUudIDwYUfl94M3PejPHG7Vopw5hN9V8WsMkSFpm3tZP3Fesz89EyrfQ==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz", + "integrity": "sha512-IuaLjruM0vMKhUUT51fQdQzBYTX49dLj8w68ALEAe2A4iYNpIC4eMac67mt3NzycvjOlf07/kYxJDc0RTl1Wqw==", "dev": true, "requires": { "loader-utils": "^1.1.0", @@ -9983,10 +8272,9 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" }, "minipass": { "version": "2.3.5", @@ -10007,9 +8295,9 @@ } }, "minizlib": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.1.tgz", - "integrity": "sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", + "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", "dev": true, "requires": { "minipass": "^2.2.1" @@ -10074,17 +8362,25 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "requires": { "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } } }, "moment": { - "version": "2.22.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", - "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" }, "moment-es6": { "version": "1.0.0", @@ -10109,9 +8405,9 @@ } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" }, "multicast-dns": { "version": "6.2.3", @@ -10136,9 +8432,9 @@ "dev": true }, "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz", + "integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==", "dev": true }, "nanomatch": { @@ -10158,26 +8454,6 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } } }, "negotiator": { @@ -10198,9 +8474,9 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "ng-packagr": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-4.4.0.tgz", - "integrity": "sha512-dLpC/kmQsdbkL96ZclGjNRhq/J4MwpPKwPYNom74lvXqFC2jbbT/fnwmxX9WKXjvE8MEGsg2D2x8MsRURiNscg==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-4.7.0.tgz", + "integrity": "sha512-FNCe4WpHwBk107pCX0KOnsv+cUaM2bCGAD/oYUl0FIwQXkI+iYjDik9KlqJ/bWDUsiCUxiAH2v5AsTaEF7G4bw==", "dev": true, "requires": { "@ngtools/json-schema": "^1.1.0", @@ -10217,14 +8493,15 @@ "less-plugin-npm-import": "^2.1.0", "node-sass": "^4.9.3", "node-sass-tilde-importer": "^1.0.0", + "opencollective": "^1.0.3", "postcss": "^7.0.0", "postcss-url": "^8.0.0", "read-pkg-up": "^4.0.0", "rimraf": "^2.6.1", - "rollup": "^0.66.0", + "rollup": "^0.67.0", "rollup-plugin-commonjs": "^9.1.3", "rollup-plugin-json": "^3.1.0", - "rollup-plugin-node-resolve": "^3.0.0", + "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-sourcemaps": "^0.4.2", "rxjs": "^6.0.0", "stylus": "^0.54.5", @@ -10232,238 +8509,6 @@ "update-notifier": "^2.3.0" }, "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -10473,114 +8518,6 @@ "locate-path": "^3.0.0" } }, - "fs-extra": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.0.tgz", - "integrity": "sha512-EglNDLRpmaTWiD/qraZn6HREAEAHJcJOmxNEYwq6xeMKnVMAy3GUcFB+wXt2C6k4CNvB/mP1y/U3dzvKKj5OtQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -10603,31 +8540,10 @@ "path-exists": "^3.0.0" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -10698,6 +8614,16 @@ "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz", "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc=" }, + "node-fetch": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", + "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", + "dev": true, + "requires": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, "node-fetch-npm": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz", @@ -10737,16 +8663,16 @@ "dependencies": { "semver": { "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", "dev": true } } }, "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.0.tgz", + "integrity": "sha512-5MQunG/oyOaBdttrL40dA7bUfPORLRWMUJLQtMg7nluxUvk5XwnLdL9twQHFAjRx/y7mIMkLKT9++qPbbk6BZA==", "dev": true, "requires": { "assert": "^1.1.1", @@ -10756,7 +8682,7 @@ "constants-browserify": "^1.0.0", "crypto-browserify": "^3.11.0", "domain-browser": "^1.1.1", - "events": "^1.0.0", + "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "0.0.0", @@ -10770,7 +8696,7 @@ "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", "url": "^0.11.0", - "util": "^0.10.3", + "util": "^0.11.0", "vm-browserify": "0.0.4" }, "dependencies": { @@ -10782,10 +8708,19 @@ } } }, + "node-releases": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.7.tgz", + "integrity": "sha512-bKdrwaqJUPHqlCzDD7so/R+Nk0jGv9a11ZhLrD9f6i947qGLrGAhU3OxRENa19QQmwzGy/g6zCDEuLGDO8HPvA==", + "dev": true, + "requires": { + "semver": "^5.3.0" + } + }, "node-sass": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.9.3.tgz", - "integrity": "sha512-XzXyGjO+84wxyH7fV6IwBOTrEBe2f0a6SBze9QWWYR/cL74AcQUks2AsqcCZenl/Fp/JVbuEaLpgrLtocwBUww==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz", + "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==", "dev": true, "requires": { "async-foreach": "^0.1.3", @@ -10803,7 +8738,7 @@ "nan": "^2.10.0", "node-gyp": "^3.8.0", "npmlog": "^4.0.0", - "request": "2.87.0", + "request": "^2.88.0", "sass-graph": "^2.2.4", "stdout-stream": "^1.4.0", "true-case-path": "^1.0.2" @@ -10817,7 +8752,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -10828,34 +8763,6 @@ "supports-color": "^2.0.0" } }, - "request": { - "version": "2.87.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", - "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", - "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "tough-cookie": "~2.3.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" - } - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -10873,6 +8780,12 @@ "find-parent-dir": "^0.3.0" } }, + "node-stream-zip": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.8.0.tgz", + "integrity": "sha512-sFMswrGIZ8c4a9o82MiET1k/XMqnkVkoU/C4mL869ndDnzPLeVKWn/6qMdzGtZCbWeuZ9IRIbhHLliSs7QTEKg==", + "dev": true + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -10883,9 +8796,9 @@ } }, "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.2.tgz", + "integrity": "sha512-YcMnjqeoUckXTPKZSAsPjUPLxH85XotbpqK3w4RyCwdFQSU5FxxBys8buehkSfg0j9fKvV1hn7O0+8reEgkAiw==", "dev": true, "requires": { "hosted-git-info": "^2.1.4", @@ -10910,9 +8823,9 @@ "dev": true }, "npm-bundled": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz", - "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", + "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", "dev": true }, "npm-package-arg": { @@ -10928,15 +8841,24 @@ } }, "npm-packlist": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.12.tgz", - "integrity": "sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.1.tgz", + "integrity": "sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==", "dev": true, "requires": { "ignore-walk": "^3.0.1", "npm-bundled": "^1.0.1" } }, + "npm-path": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-2.0.4.tgz", + "integrity": "sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw==", + "dev": true, + "requires": { + "which": "^1.2.10" + } + }, "npm-pick-manifest": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz", @@ -10949,9 +8871,9 @@ } }, "npm-registry-fetch": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-3.8.0.tgz", - "integrity": "sha512-hrw8UMD+Nob3Kl3h8Z/YjmKamb1gf7D1ZZch2otrIXM3uFLB5vjEY6DhMlq80z/zZet6eETLbOXcuQudCB3Zpw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-3.9.0.tgz", + "integrity": "sha512-srwmt8YhNajAoSAaDWndmZgx89lJwIZ1GWxOuckH4Coek4uHv5S+o/l9FLQe/awA+JwTnj4FJHldxhlXdZEBmw==", "dev": true, "requires": { "JSONStream": "^1.3.4", @@ -10971,6 +8893,17 @@ "path-key": "^2.0.0" } }, + "npm-which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-3.0.1.tgz", + "integrity": "sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo=", + "dev": true, + "requires": { + "commander": "^2.9.0", + "npm-path": "^2.0.2", + "which": "^1.2.10" + } + }, "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", @@ -11002,9 +8935,9 @@ "dev": true }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, "object-assign": { @@ -11038,6 +8971,15 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -11048,14 +8990,6 @@ "dev": true, "requires": { "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "object.omit": { @@ -11066,6 +9000,17 @@ "requires": { "for-own": "^0.1.4", "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } } }, "object.pick": { @@ -11075,14 +9020,6 @@ "dev": true, "requires": { "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "obuf": { @@ -11124,10 +9061,138 @@ "mimic-fn": "^1.0.0" } }, + "opencollective": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", + "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", + "dev": true, + "requires": { + "babel-polyfill": "6.23.0", + "chalk": "1.1.3", + "inquirer": "3.0.6", + "minimist": "1.2.0", + "node-fetch": "1.6.3", + "opn": "4.0.2" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "inquirer": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz", + "integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=", + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "chalk": "^1.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.1", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx": "^4.1.0", + "string-width": "^2.0.0", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "opn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", + "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, "opn": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.3.0.tgz", - "integrity": "sha512-bYJHo/LOmoTd+pfiYhfZDnf9zekVJrY+cnS2a5F2x+w5ppvTqObojTP7WiFG+kVZs9Inw+qQ/lw7TroWwhdd2g==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.4.0.tgz", + "integrity": "sha512-YF9MNdVy/0qvJvDtunAOzFw9iasOQHpVthTCvGzxt61Il64AYSGdK+rYwld7NAfk9qJ7dt+hymBNSc9LNYS+Sw==", "dev": true, "requires": { "is-wsl": "^1.1.0" @@ -11141,26 +9206,18 @@ "requires": { "minimist": "~0.0.1", "wordwrap": "~0.0.2" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" }, "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true } } @@ -11182,22 +9239,28 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, "os-locale": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "dev": true, "requires": { "lcid": "^1.0.0" } }, + "os-shim": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", + "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=", + "dev": true + }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, @@ -11224,9 +9287,9 @@ "dev": true }, "p-is-promise": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", - "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.0.0.tgz", + "integrity": "sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg==", "dev": true }, "p-limit": { @@ -11272,17 +9335,17 @@ } }, "pacote": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.1.1.tgz", - "integrity": "sha512-f28Rq5ozzKAA9YwIKw61/ipwAatUZseYmVssDbHHaexF0wRIVotapVEZPAjOT7Eu3LYVqEp0NVpNizoAnYBUaA==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.4.0.tgz", + "integrity": "sha512-WQ1KL/phGMkedYEQx9ODsjj7xvwLSpdFJJdEXrLyw5SILMxcTNt5DTxT2Z93fXuLFYJBlZJdnwdalrQdB/rX5w==", "dev": true, "requires": { - "bluebird": "^3.5.2", - "cacache": "^11.2.0", + "bluebird": "^3.5.3", + "cacache": "^11.3.2", "figgy-pudding": "^3.5.1", "get-stream": "^4.1.0", "glob": "^7.1.3", - "lru-cache": "^4.1.3", + "lru-cache": "^5.1.1", "make-fetch-happen": "^4.0.1", "minimatch": "^3.0.4", "minipass": "^2.3.5", @@ -11291,7 +9354,7 @@ "normalize-package-data": "^2.4.0", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.1.12", - "npm-pick-manifest": "^2.1.0", + "npm-pick-manifest": "^2.2.3", "npm-registry-fetch": "^3.8.0", "osenv": "^0.1.5", "promise-inflight": "^1.0.1", @@ -11301,36 +9364,30 @@ "safe-buffer": "^5.1.2", "semver": "^5.6.0", "ssri": "^6.0.1", - "tar": "^4.4.6", + "tar": "^4.4.8", "unique-filename": "^1.1.1", "which": "^1.3.1" }, "dependencies": { - "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==", - "dev": true - }, "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", "dev": true, "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" } }, @@ -11343,18 +9400,13 @@ "pump": "^3.0.0" } }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "yallist": "^3.0.2" } }, "mississippi": { @@ -11385,12 +9437,6 @@ "once": "^1.3.1" } }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - }, "ssri": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", @@ -11424,9 +9470,9 @@ } }, "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.8.tgz", + "integrity": "sha512-6i0HVbUfcKaTv+EG8ZTr75az7GFXcLYk9UyLEg7Notv/Ma+z/UG3TCoz6GiNeOrn1E/e63I0X/Hpw18jHOTUnA==", "dev": true }, "parallel-transform": { @@ -11441,16 +9487,17 @@ } }, "parse-asn1": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", + "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", "dev": true, "requires": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, "parse-glob": { @@ -11463,6 +9510,23 @@ "is-dotfile": "^1.0.0", "is-extglob": "^1.0.0", "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + } } }, "parse-json": { @@ -11481,10 +9545,10 @@ "dev": true }, "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", + "optional": true }, "parseqs": { "version": "0.0.5", @@ -11518,7 +9582,7 @@ }, "path-browserify": { "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "resolved": "http://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", "dev": true }, @@ -11536,7 +9600,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, @@ -11553,9 +9617,9 @@ "dev": true }, "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, "path-to-regexp": { @@ -11587,12 +9651,12 @@ } }, "pdfjs-dist": { - "version": "2.0.489", - "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.0.489.tgz", - "integrity": "sha1-Y+VLKSqGeQpFRpfrRNQ0e4+/rSc=", + "version": "2.0.943", + "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.0.943.tgz", + "integrity": "sha512-iLhNcm4XceTHRaSU5o22ZGCm4YpuW5+rf4+BJFH/feBhMQLbCGBry+Jet8Q419QDI4qgARaIQzXuiNrsNWS8Yw==", "requires": { "node-ensure": "^0.0.0", - "worker-loader": "^1.1.1" + "worker-loader": "^2.0.0" } }, "performance-now": { @@ -11631,10 +9695,19 @@ "find-up": "^2.1.0" } }, + "please-upgrade-node": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz", + "integrity": "sha512-KY1uHnQ2NlQHqIJQpnh/i54rKkuxCEBx+voJIS/Mvb+L2iYd2NMotwduhKTMjfC1uKoX3VXOxLjIYG66dfJTVQ==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, "portfinder": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.17.tgz", - "integrity": "sha512-syFcRIRzVI1BoEFOCaAiizwDolh1S1YXSodsVhncbhjzjZQulhczNRbqnUl9N31Q4dKGOXsNDqxC2BWBgSMqeQ==", + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.20.tgz", + "integrity": "sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw==", "dev": true, "requires": { "async": "^1.5.2", @@ -11656,6 +9729,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -11666,14 +9745,14 @@ "dev": true }, "postcss": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.5.tgz", - "integrity": "sha512-HBNpviAUFCKvEh7NZhw1e8MBPivRszIiUnhrJ+sBFVSYSqubrzwX3KG51mYgcRHX8j/cAgZJedONZcm5jTBdgQ==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", + "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", "dev": true, "requires": { - "chalk": "^2.4.1", + "chalk": "^2.4.2", "source-map": "^0.6.1", - "supports-color": "^5.5.0" + "supports-color": "^6.1.0" }, "dependencies": { "source-map": { @@ -11681,22 +9760,13 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, "postcss-import": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.0.tgz", - "integrity": "sha512-3KqKRZcaZAvxbY8DVLdd81tG5uKzbUQuiWIvy0o0fzEC42bKacqPYFWbfCQyw6L4LWUaqPz/idvIdbhpgQ32eQ==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", + "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", "dev": true, "requires": { "postcss": "^7.0.1", @@ -11754,24 +9824,51 @@ }, "dependencies": { "mime": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.3.1.tgz", - "integrity": "sha512-OEUllcVoydBHGN1z84yfQDimn58pZNNNXgZlHXSboxMlFvgI6MXSWpWKpFRra7H1HxpVhHTkrghfRW49k6yjeg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", "dev": true } } }, "postcss-value-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", - "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true + "pre-commit": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/pre-commit/-/pre-commit-1.2.2.tgz", + "integrity": "sha1-287g7p3nI15X95xW186UZBpp7sY=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "spawn-sync": "^1.0.15", + "which": "1.2.x" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "which": { + "version": "1.2.14", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", + "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } }, "prepend-http": { "version": "1.0.4", @@ -11786,9 +9883,9 @@ "dev": true }, "prettier": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.15.2.tgz", - "integrity": "sha512-YgPLFFA0CdKL4Eg2IHtUSjzj/BWgszDHiNQAe0VAIBse34148whfdzLagRL+QiKS+YfK5ftB6X4v/MBw8yCoug==", + "version": "1.16.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz", + "integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==", "dev": true }, "process": { @@ -11828,6 +9925,12 @@ "retry": "^0.10.0" } }, + "property-expr": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-1.5.1.tgz", + "integrity": "sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g==", + "dev": true + }, "protoduck": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", @@ -11838,12 +9941,11 @@ } }, "protractor": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.0.tgz", - "integrity": "sha512-6TSYqMhUUzxr4/wN0ttSISqPMKvcVRXF4k8jOEpGWD8OioLak4KLgfzHK9FJ49IrjzRrZ+Mx1q2Op8Rk0zEcnQ==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/protractor/-/protractor-5.4.2.tgz", + "integrity": "sha512-zlIj64Cr6IOWP7RwxVeD8O4UskLYPoyIcg0HboWJL9T79F1F0VWtKkGTr/9GN6BKL+/Q/GmM7C9kFVCfDbP5sA==", "dev": true, "requires": { - "@types/node": "^6.0.46", "@types/q": "^0.0.32", "@types/selenium-webdriver": "^3.0.0", "blocking-proxy": "^1.0.0", @@ -11857,16 +9959,10 @@ "saucelabs": "^1.5.0", "selenium-webdriver": "3.6.0", "source-map-support": "~0.4.0", - "webdriver-js-extender": "2.0.0", + "webdriver-js-extender": "2.1.0", "webdriver-manager": "^12.0.6" }, "dependencies": { - "@types/node": { - "version": "6.0.117", - "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.117.tgz", - "integrity": "sha512-sihk0SnN8PpiS5ihu5xJQ5ddnURNq4P+XPmW+nORlKkHy21CoZO/IVHK/Wq/l3G8fFW06Fkltgnqx229uPlnRg==", - "dev": true - }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -11875,7 +9971,7 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { @@ -11903,7 +9999,7 @@ }, "globby": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "resolved": "http://registry.npmjs.org/globby/-/globby-5.0.0.tgz", "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { @@ -11915,24 +10011,12 @@ "pinkie-promise": "^2.0.0" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true }, - "q": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", - "dev": true - }, "selenium-webdriver": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-3.6.0.tgz", @@ -11945,6 +10029,21 @@ "xml2js": "^0.4.17" } }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -11961,9 +10060,9 @@ } }, "webdriver-manager": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.0.tgz", - "integrity": "sha512-oEc5fmkpz6Yh6udhwir5m0eN5mgRPq9P/NU5YWuT3Up5slt6Zz+znhLU7q4+8rwCZz/Qq3Fgpr/4oao7NPCm2A==", + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/webdriver-manager/-/webdriver-manager-12.1.1.tgz", + "integrity": "sha512-L9TEQmZs6JbMMRQI1w60mfps265/NCr0toYJl7p/R2OAk6oXAfwI6jqYP7EWae+d7Ad2S2Aj4+rzxoSjqk3ZuA==", "dev": true, "requires": { "adm-zip": "^0.4.9", @@ -11981,6 +10080,31 @@ } } }, + "protractor-screenshoter-plugin": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/protractor-screenshoter-plugin/-/protractor-screenshoter-plugin-0.10.3.tgz", + "integrity": "sha512-OF9kGe1rMxBQY4uXzXQUFT14EB83rz8DlDcxmH5HcOHPBpUhGh+Nwo7+K87w1LoLcTuGdG7Bz+/hGwoGguDfsA==", + "dev": true, + "requires": { + "circular-json": "^0.5.1", + "fs-extra": "^7.0.0", + "klaw-sync": "^6.0.0", + "lodash": "^4.17.11", + "mkdirp": "^0.5.1", + "moment": "^2.20.1", + "q": "^1.5.1", + "screenshoter-report-analyzer": "^0.6", + "uuid": "^3.1.0" + }, + "dependencies": { + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + } + } + }, "proxy-addr": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", @@ -12004,9 +10128,9 @@ "dev": true }, "psl": { - "version": "1.1.29", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "version": "1.1.31", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", + "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==", "dev": true }, "public-encrypt": { @@ -12050,9 +10174,9 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", + "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", "dev": true }, "qjobs": { @@ -12062,9 +10186,9 @@ "dev": true }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.6.0.tgz", + "integrity": "sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA==" }, "querystring": { "version": "0.2.0", @@ -12085,9 +10209,9 @@ "dev": true }, "randomatic": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz", - "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", "dev": true, "requires": { "is-number": "^4.0.0", @@ -12100,12 +10224,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -12135,55 +10253,40 @@ "dev": true }, "raw-body": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", - "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "raw-loader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-1.0.0.tgz", + "integrity": "sha512-Uqy5AqELpytJTRxYT4fhltcKPj0TyaEpzJDcGz7DFJi+pQOOi3GjR/DOdxTkTsF+NzhnldIoG6TORaBlInUuqA==", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.2", - "iconv-lite": "0.4.19", - "unpipe": "1.0.0" + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" }, "dependencies": { - "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", - "dev": true - }, - "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "depd": "1.1.1", - "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } - }, - "iconv-lite": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", - "dev": true - }, - "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", - "dev": true } } }, - "raw-loader": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", - "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", - "dev": true - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -12194,14 +10297,6 @@ "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } } }, "read-cache": { @@ -12215,7 +10310,7 @@ "dependencies": { "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -12245,7 +10340,7 @@ }, "pify": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } @@ -12284,7 +10379,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -12297,15 +10392,14 @@ } }, "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } }, "rechoir": { @@ -12328,9 +10422,9 @@ } }, "reflect-metadata": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", - "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==", "dev": true }, "regenerate": { @@ -12366,7 +10460,7 @@ }, "regexpu-core": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", "dev": true, "requires": { @@ -12396,13 +10490,13 @@ }, "regjsgen": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", "dev": true }, "regjsparser": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "resolved": "http://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { @@ -12411,7 +10505,7 @@ "dependencies": { "jsesc": { "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", "dev": true } @@ -12424,9 +10518,9 @@ "dev": true }, "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", "dev": true }, "repeat-string": { @@ -12472,102 +10566,11 @@ "uuid": "^3.3.2" }, "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "har-schema": "^2.0.0" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } } } }, @@ -12596,13 +10599,10 @@ "dev": true }, "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true }, "resolve-cwd": { "version": "2.0.0", @@ -12653,16 +10653,6 @@ "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", "dev": true }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "optional": true, - "requires": { - "align-text": "^0.1.1" - } - }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", @@ -12683,9 +10673,9 @@ } }, "rollup": { - "version": "0.66.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.66.6.tgz", - "integrity": "sha512-J7/SWanrcb83vfIHqa8+aVVGzy457GcjA6GVZEnD0x2u4OnOd0Q1pCrEoNe8yLwM6z6LZP02zBT2uW0yh5TqOw==", + "version": "0.67.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.67.4.tgz", + "integrity": "sha512-AVuP73mkb4BBMUmksQ3Jw0jTrBTU1i7rLiUYjFxLZGb3xiFmtVEg40oByphkZAsiL0bJC3hRAJUQos/e5EBd+w==", "dev": true, "requires": { "@types/estree": "0.0.39", @@ -12702,6 +10692,17 @@ "magic-string": "^0.25.1", "resolve": "^1.8.1", "rollup-pluginutils": "^2.3.3" + }, + "dependencies": { + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } } }, "rollup-plugin-json": { @@ -12714,21 +10715,30 @@ } }, "rollup-plugin-node-resolve": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.4.0.tgz", - "integrity": "sha512-PJcd85dxfSBWih84ozRtBkB731OjXk0KnzN0oGp7WOWcarAFkVa71cV5hTJg2qpVsV2U8EUwrzHP3tvy9vS3qg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.0.tgz", + "integrity": "sha512-7Ni+/M5RPSUBfUaP9alwYQiIKnKeXCOHiqBpKUl9kwp3jX5ZJtgXAait1cne6pGEVUUztPD6skIKH9Kq9sNtfw==", "dev": true, "requires": { - "builtin-modules": "^2.0.0", + "builtin-modules": "^3.0.0", "is-module": "^1.0.0", - "resolve": "^1.1.6" + "resolve": "^1.8.1" }, "dependencies": { "builtin-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-2.0.0.tgz", - "integrity": "sha512-3U5kUA5VPsRUA3nofm/BXX7GVHKfxz0hOBAPxXrIvHzlDRkQVqEn6yi8QJegxl4LzOHLdvb7XF5dVawa/VVYBg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.0.0.tgz", + "integrity": "sha512-hMIeU4K2ilbXV6Uv93ZZ0Avg/M91RaKXucQ+4me2Do1txxBDyDZWCBa5bJSLqoNTRpXTLwEzIk1KmloenDDjhg==", "dev": true + }, + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, @@ -12750,6 +10760,97 @@ "requires": { "estree-walker": "^0.5.2", "micromatch": "^2.3.11" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + } } }, "run-async": { @@ -12777,23 +10878,23 @@ "dev": true }, "rxjs": { - "version": "6.3.3", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", - "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", + "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", "requires": { "tslib": "^1.9.0" } }, "rxjs-stream": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/rxjs-stream/-/rxjs-stream-2.0.3.tgz", - "integrity": "sha512-i8sN1i6hld1n0gK8pJEtJIERwz5MgpRvVx3US9tPG1ynJSonFq/VlRx2DFSx0zTyhE4Vl96/rIYSZ6lJdP810g==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/rxjs-stream/-/rxjs-stream-3.0.1.tgz", + "integrity": "sha512-KZ+B7MWw2mygAsLJJ+mjYkCXHtSeYRXWhUVQBQRX4NgBmEiAEGAmVz7epY+8Gj0REL22W0T8ZbysFbzI/76ikA==", "dev": true }, "rxjs-tslint-rules": { - "version": "4.11.0", - "resolved": "https://registry.npmjs.org/rxjs-tslint-rules/-/rxjs-tslint-rules-4.11.0.tgz", - "integrity": "sha512-db6M2YXcFydih7dLHcPgI73iYkui5QoZXLkKgpuZrs9WRS03JCbESwed4XeL3ZsOaS/JftqfLC6Q2RcOHxBs7w==", + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/rxjs-tslint-rules/-/rxjs-tslint-rules-4.16.2.tgz", + "integrity": "sha512-yX/rG/aqjIZNTv6Ugq9ST43IV+g2a3JY3YwWTA8Q7VY+jGRhoILLWJbvJlL5gwmeT4HZXybpVGEBsZU4NPx15g==", "dev": true, "requires": { "@phenomnomnominal/tsquery": "^3.0.0", @@ -12812,20 +10913,14 @@ "xregexp": "4.0.0" } }, - "tsutils": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.4.0.tgz", - "integrity": "sha512-lJOYR+rsCnso8k7C/D1IVSgOmJS9Ds8U4P2H7CxBtTf1w227Zg2nk+Fod8AsUzu3msg8AjZVsNBJb5QgCZsBjQ==", + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { - "tslib": "^1.8.1" + "path-parse": "^1.0.6" } - }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true } } }, @@ -12836,7 +10931,7 @@ }, "safe-regex": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { @@ -12886,19 +10981,25 @@ }, "sax": { "version": "0.5.8", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", + "resolved": "http://registry.npmjs.org/sax/-/sax-0.5.8.tgz", "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", "dev": true }, "schema-utils": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", + "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", "requires": { "ajv": "^6.1.0", "ajv-keywords": "^3.1.0" } }, + "screenshoter-report-analyzer": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/screenshoter-report-analyzer/-/screenshoter-report-analyzer-0.6.0.tgz", + "integrity": "sha1-Cm+I1fXRrBa2z3Ji7/ujH+5I7RI=", + "dev": true + }, "scss-tokenizer": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", @@ -12911,7 +11012,7 @@ "dependencies": { "source-map": { "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { @@ -12959,9 +11060,15 @@ } }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", "dev": true }, "semver-diff": { @@ -13026,13 +11133,19 @@ "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, "serialize-javascript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.6.1.tgz", + "integrity": "sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw==", "dev": true }, "serve-index": { @@ -13058,6 +11171,12 @@ "requires": { "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -13079,12 +11198,6 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -13122,7 +11235,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -13181,16 +11294,42 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true }, + "simple-git": { + "version": "1.107.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-1.107.0.tgz", + "integrity": "sha512-t4OK1JRlp4ayKRfcW6owrWcRVLyHRUlhGd0uN6ZZTqfDq8a5XpcUdOKiGRNobHEuMtNqzp0vcJNvhYWwh5PsQA==", + "dev": true, + "requires": { + "debug": "^4.0.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", "dev": true }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, "smart-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.1.tgz", - "integrity": "sha512-RFqinRVJVcCAL9Uh1oVqE6FZkqsyLiVOYEZ20TqIOjuX7iFVJ+zsbs4RIghnw/pTs7mZvt8ZHhvm1ZUrR4fykg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", + "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==", "dev": true }, "snapdragon": { @@ -13235,6 +11374,18 @@ "requires": { "is-extendable": "^0.1.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true } } }, @@ -13286,18 +11437,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -13308,6 +11447,17 @@ "dev": true, "requires": { "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "socket.io": { @@ -13322,6 +11472,23 @@ "socket.io-adapter": "~1.1.0", "socket.io-client": "2.1.1", "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "socket.io-adapter": { @@ -13350,11 +11517,28 @@ "parseuri": "0.0.5", "socket.io-parser": "~3.2.0", "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "socket.io-parser": { "version": "3.2.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", "dev": true, "requires": { @@ -13363,11 +11547,26 @@ "isarray": "2.0.1" }, "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "isarray": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true } } }, @@ -13388,1097 +11587,614 @@ "dev": true, "requires": { "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "faye-websocket": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", - "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, - "socks": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.2.tgz", - "integrity": "sha512-g6wjBnnMOZpE0ym6e0uHSddz9p3a+WsBaaYQaBaSCJYvrC4IXykQR9MNGjLQf38e9iIIhp3b1/Zk8YZI3KGJ0Q==", - "dev": true, - "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.0.1" - } - }, - "socks-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", - "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", - "dev": true, - "requires": { - "agent-base": "~4.2.0", - "socks": "~2.2.0" - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-loader": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", - "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", - "dev": true, - "requires": { - "async": "^2.5.0", - "loader-utils": "^1.1.0" - } - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", - "dev": true, - "requires": { - "source-map": "^0.5.6" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sourcemap-codec": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.3.tgz", - "integrity": "sha512-vFrY/x/NdsD7Yc8mpTJXuao9S8lq08Z/kOITHz6b7YbfI9xL8Spe5EvSQUHOI7SbpY8bRPr0U3kKSsPuqEGSfA==", - "dev": true - }, - "spdx-correct": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", - "dev": true - }, - "spdy": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", - "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", - "dev": true, - "requires": { - "debug": "^2.6.8", - "handle-thing": "^1.2.5", - "http-deceiver": "^1.2.7", - "safe-buffer": "^5.0.1", - "select-hose": "^2.0.0", - "spdy-transport": "^2.0.18" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "spdy-transport": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.1.tgz", - "integrity": "sha512-q7D8c148escoB3Z7ySCASadkegMmUZW8Wb/Q1u0/XBgDKMO880rLQDj8Twiew/tYi7ghemKUi/whSYOwE17f5Q==", - "dev": true, - "requires": { - "debug": "^2.6.8", - "detect-node": "^2.0.3", - "hpack.js": "^2.1.6", - "obuf": "^1.1.1", - "readable-stream": "^2.2.9", - "safe-buffer": "^5.0.1", - "wbuf": "^1.7.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "speed-measure-webpack-plugin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.2.3.tgz", - "integrity": "sha512-p+taQ69VkRUXYMoZOx2nxV/Tz8tt79ahctoZJyJDHWP7fEYvwFNf5Pd73k5kZ6auu0pTsPNLEUwWpM8mCk85Zw==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } - } - }, - "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.1" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "websocket-driver": ">=0.5.1" } } } }, - "stats-webpack-plugin": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.7.0.tgz", - "integrity": "sha512-NT0YGhwuQ0EOX+uPhhUcI6/+1Sq/pMzNuSCBVT4GbFl/ac6I/JZefBcjlECNfAb1t3GOx5dEj1Z7x0cAxeeVLQ==", + "socks": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.2.3.tgz", + "integrity": "sha512-+2r83WaRT3PXYoO/1z+RDEBE7Z2f9YcdQnJ0K/ncXXbV5gJ6wYfNAebYFYiiUjM6E4JyXnPY8cimwyvFYHVUUA==", "dev": true, "requires": { - "lodash": "^4.17.4" + "ip": "^1.1.5", + "smart-buffer": "4.0.2" } }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - }, - "stdout-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", - "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", + "socks-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz", + "integrity": "sha512-Kezx6/VBguXOsEe5oU3lXYyKMi4+gva72TwJ7pQY5JfqUx2nMk7NXA6z/mpNqIlfQjWYVfeuNvQjexiTaTn6Nw==", "dev": true, "requires": { - "readable-stream": "^2.0.1" + "agent-base": "~4.2.0", + "socks": "~2.2.0" } }, - "stream-browserify": { + "source-list-map": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "source-map-loader": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", + "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", "dev": true, "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" + "async": "^2.5.0", + "loader-utils": "^1.1.0" } }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "source-map-support": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", + "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "sourcemap-codec": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz", + "integrity": "sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg==", + "dev": true + }, + "spawn-sync": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", + "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "concat-stream": "^1.4.7", + "os-shim": "^0.1.2" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "dev": true, "requires": { - "get-stdin": "^4.0.1" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", "dev": true }, - "style-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", - "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "spdy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.0.tgz", + "integrity": "sha512-ot0oEGT/PGUpzf/6uk4AWLqkq+irlqHXkrdbk51oWONh3bxQmBuljxPNl66zlRRcIJStWq0QkLUCPOPjgjvU0Q==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" }, "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "ms": "^2.1.1" } } } }, - "stylus": { - "version": "0.54.5", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz", - "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", "dev": true, "requires": { - "css-parse": "1.7.x", - "debug": "*", - "glob": "7.0.x", - "mkdirp": "0.5.x", - "sax": "0.5.x", - "source-map": "0.1.x" + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" }, "dependencies": { - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "ms": "^2.1.1" } }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "readable-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.1.1.tgz", + "integrity": "sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA==", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } } } }, - "stylus-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", - "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", + "speed-measure-webpack-plugin": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/speed-measure-webpack-plugin/-/speed-measure-webpack-plugin-1.3.0.tgz", + "integrity": "sha512-b9Yd0TrzceMVYSbuamM1sFsGM1oVfyFTM22gOoyLhymNvBVApuYpkdFOgYkKJpN/KhTpcCYcTGHg7X+FJ33Vvw==", "dev": true, "requires": { - "loader-utils": "^1.0.2", - "lodash.clonedeep": "^4.5.0", - "when": "~3.6.x" - } - }, - "superagent": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", - "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", - "requires": { - "component-emitter": "^1.2.0", - "cookiejar": "^2.1.0", - "debug": "^3.1.0", - "extend": "^3.0.0", - "form-data": "^2.3.1", - "formidable": "^1.1.1", - "methods": "^1.1.1", - "mime": "^1.4.1", - "qs": "^6.5.1", - "readable-stream": "^2.0.5" + "chalk": "^2.0.1" } }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true + "requires": { + "extend-shallow": "^3.0.0" + } }, - "tapable": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", - "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", + "sprintf-js": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "dev": true, "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" } }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "ssri": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", + "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", "dev": true, "requires": { - "execa": "^0.7.0" + "safe-buffer": "^5.1.1" } }, - "terser": { - "version": "3.10.12", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.10.12.tgz", - "integrity": "sha512-3ODPC1eVt25EVNb04s/PkHxOmzKBQUF6bwwuR6h2DbEF8/j265Y1UkwNtOk9am/pRxfJ5HPapOlUlO6c16mKQQ==", + "staged-git-files": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/staged-git-files/-/staged-git-files-1.1.2.tgz", + "integrity": "sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA==", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1", - "source-map-support": "~0.5.6" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "is-descriptor": "^0.1.0" } } } }, - "terser-webpack-plugin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.1.0.tgz", - "integrity": "sha512-61lV0DSxMAZ8AyZG7/A4a3UPlrbOBo8NIQ4tJzLPAdGOQ+yoNC7l5ijEow27lBAL2humer01KLS6bGIMYQxKoA==", + "stats-webpack-plugin": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/stats-webpack-plugin/-/stats-webpack-plugin-0.7.0.tgz", + "integrity": "sha512-NT0YGhwuQ0EOX+uPhhUcI6/+1Sq/pMzNuSCBVT4GbFl/ac6I/JZefBcjlECNfAb1t3GOx5dEj1Z7x0cAxeeVLQ==", "dev": true, "requires": { - "cacache": "^11.0.2", - "find-cache-dir": "^2.0.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "terser": "^3.8.1", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" - }, - "dependencies": { - "cacache": { - "version": "11.3.1", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.1.tgz", - "integrity": "sha512-2PEw4cRRDu+iQvBTTuttQifacYjLPhET+SYO/gEFMy8uhi+jlJREDAjSF5FWSdV/Aw5h18caHA7vMTw2c+wDzA==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "figgy-pudding": "^3.1.0", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.3", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^6.0.0", - "unique-filename": "^1.1.0", - "y18n": "^4.0.0" - } - }, - "find-cache-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", - "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", - "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - } + "lodash": "^4.17.4" } }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", "dev": true }, - "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", "dev": true, "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "readable-stream": "^2.0.1" } }, - "thunky": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", - "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", - "dev": true - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } }, - "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", "dev": true, "requires": { - "setimmediate": "^1.0.4" + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" } }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "dev": true, "requires": { - "os-tmpdir": "~1.0.2" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true + "streamroller": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", + "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + } }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "string-argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz", + "integrity": "sha1-2sMECGkMIfPDYwo/86BYd73L1zY=", "dev": true }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "string-width": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "safe-buffer": "~5.1.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - } + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" } }, - "topo": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.0.tgz", - "integrity": "sha512-Tlu1fGlR90iCdIPURqPiufqAlCZYzLjHYVVbcFWDMcX7+tK8hdZWAfsMrD/pBul9jqHHwFjNdf1WaxA9vTRRhw==", + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "hoek": "5.x.x" + "ansi-regex": "^2.0.0" } }, - "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } + "is-utf8": "^0.2.0" } }, - "tree-kill": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.0.tgz", - "integrity": "sha512-DlX6dR0lOIRDFxI0mjL9IYg6OTncLm/Zt+JiBhE5OlFcAR8yc9S7FFXU9so0oda47frdM/JFsk7UjNt9vscKcg==", - "dev": true - }, - "trim-newlines": { + "strip-eof": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "trim-right": { + "strip-indent": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, - "true-case-path": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz", - "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=", + "style-loader": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", "dev": true, "requires": { - "glob": "^6.0.4" + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" }, "dependencies": { - "glob": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", - "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } }, - "ts-node": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-4.1.0.tgz", - "integrity": "sha512-xcZH12oVg9PShKhy3UHyDmuDLV3y7iKwX25aMVPt1SIXSuAfWkFiGPEkg+th8R4YKW/QCxDoW7lJdb15lx6QWg==", + "stylus": { + "version": "0.54.5", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz", + "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", "dev": true, "requires": { - "arrify": "^1.0.0", - "chalk": "^2.3.0", - "diff": "^3.1.0", - "make-error": "^1.1.1", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map-support": "^0.5.0", - "tsconfig": "^7.0.0", - "v8flags": "^3.0.0", - "yn": "^2.0.0" + "css-parse": "1.7.x", + "debug": "*", + "glob": "7.0.x", + "mkdirp": "0.5.x", + "sax": "0.5.x", + "source-map": "0.1.x" }, "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "glob": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", + "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", - "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "version": "0.1.43", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "amdefine": ">=0.0.4" } } } }, - "tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "requires": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } - } - }, - "tsickle": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.33.1.tgz", - "integrity": "sha512-SpW2G3PvDGs4a5sMXPlWnCWHWRviWjSlI3U0734e3fU3U39VAE0NPr8M3W1cuL/OU/YXheYipGeEwtIJ5k0NHQ==", + "stylus-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", "dev": true, "requires": { - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "source-map": "^0.7.3" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" } }, - "tslib": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", - "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" - }, - "tslint": { - "version": "5.11.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", - "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", - "dev": true, - "requires": { - "babel-code-frame": "^6.22.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^3.2.0", - "glob": "^7.1.1", - "js-yaml": "^3.7.0", - "minimatch": "^3.0.4", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.27.2" + "superagent": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", + "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", + "requires": { + "component-emitter": "^1.2.0", + "cookiejar": "^2.1.0", + "debug": "^3.1.0", + "extend": "^3.0.0", + "form-data": "^2.3.1", + "formidable": "^1.1.1", + "methods": "^1.1.1", + "mime": "^1.4.1", + "qs": "^6.5.1", + "readable-stream": "^2.0.5" } }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "tslib": "^1.8.1" + "has-flag": "^3.0.0" } }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "dev": true }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } + "synchronous-promise": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.6.tgz", + "integrity": "sha512-TyOuWLwkmtPL49LHCX1caIwHjRzcVd62+GF6h8W/jHOeZUFHpnd2XJDVuUlaTaLPH1nuu2M69mfHr5XbQJnf/g==", + "dev": true }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true, - "optional": true + "tapable": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", + "integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA==", + "dev": true }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "tar": { + "version": "2.2.1", + "resolved": "http://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "block-stream": "*", + "fstream": "^1.0.2", + "inherits": "2" } }, - "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", "dev": true, "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "execa": "^0.7.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } } }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", - "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==", - "dev": true - }, - "uglify-js": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", - "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", + "terser": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.16.1.tgz", + "integrity": "sha512-JDJjgleBROeek2iBcSNzOHLKsB/MdDf+E/BOAJ0Tk9r7p9/fVobfv7LMJ/g/k3v9SXdmjZnIlFd5nfn/Rt0Xow==", "dev": true, "requires": { "commander": "~2.17.1", - "source-map": "~0.6.1" + "source-map": "~0.6.1", + "source-map-support": "~0.5.9" }, "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -14487,768 +12203,865 @@ } } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true, - "optional": true - }, - "uglifyjs-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", + "terser-webpack-plugin": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.2.tgz", + "integrity": "sha512-1DMkTk286BzmfylAvLXwpJrI7dWa5BnFmscV/2dCr8+c56egFcbaeFAl7+sujAjdmpLam21XRdhA4oifLyiWWg==", "dev": true, "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "schema-utils": "^0.4.5", + "cacache": "^11.0.2", + "find-cache-dir": "^2.0.0", + "schema-utils": "^1.0.0", "serialize-javascript": "^1.4.0", "source-map": "^0.6.1", - "uglify-es": "^3.3.4", + "terser": "^3.16.1", "webpack-sources": "^1.1.0", "worker-farm": "^1.5.2" }, "dependencies": { - "commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", - "dev": true + "cacache": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz", + "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==", + "dev": true, + "requires": { + "bluebird": "^3.5.3", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.2", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "find-cache-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.0.0.tgz", + "integrity": "sha512-LDUY6V1Xs5eFskUVYtIwatojt6+9xC9Chnlk/jYOOvn3FAFfSaWddxahDGyNHh0b2dMXa6YW2m0tk8TdVaXHlA==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^1.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "p-limit": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", + "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, - "uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { - "commander": "~2.13.0", - "source-map": "~0.6.1" + "find-up": "^3.0.0" } - } - } - }, - "ultron": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", - "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" + "figgy-pudding": "^3.5.1" } + }, + "yallist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", + "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==", + "dev": true } } }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "unique-slug": "^2.0.0" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "unique-slug": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", - "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "thunky": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", + "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", + "dev": true + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", + "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { - "imurmurhash": "^0.1.4" + "setimmediate": "^1.0.4" } }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "crypto-random-string": "^1.0.0" + "os-tmpdir": "~1.0.2" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "to-array": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", + "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "kind-of": "^3.0.2" }, "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } + "is-buffer": "^1.1.5" } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true } } }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } }, - "update-notifier": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "topo": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/topo/-/topo-3.0.3.tgz", + "integrity": "sha512-IgpPtvD4kjrJ7CRA3ov2FhWQADwv+Tdqbsf1ZnPUSAtCJ9e1Z44MmoSGDXGk4IppoZA7jd/QRkNddlLJWlUZsQ==", + "dev": true, "requires": { - "punycode": "^2.1.0" + "hoek": "6.x.x" + }, + "dependencies": { + "hoek": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.2.tgz", + "integrity": "sha512-6qhh/wahGYZHFSFw12tBbJw5fsAhhwrrG/y3Cs0YMTv2WzMnL0oLPnQJjv1QJvEfylRSOFuP+xCu+tdx0tD16Q==", + "dev": true + } } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=", "dev": true }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "dev": true, "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "psl": "^1.1.24", + "punycode": "^1.4.1" }, "dependencies": { "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true } } }, - "url-parse": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", - "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", - "dev": true, - "requires": { - "querystringify": "^2.0.0", - "requires-port": "^1.0.0" - } + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true }, - "url-parse-lax": { + "trim-newlines": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", "dev": true, "requires": { - "prepend-http": "^1.0.1" + "glob": "^7.1.2" } }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true + "ts-node": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-4.1.0.tgz", + "integrity": "sha512-xcZH12oVg9PShKhy3UHyDmuDLV3y7iKwX25aMVPt1SIXSuAfWkFiGPEkg+th8R4YKW/QCxDoW7lJdb15lx6QWg==", + "dev": true, + "requires": { + "arrify": "^1.0.0", + "chalk": "^2.3.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map-support": "^0.5.0", + "tsconfig": "^7.0.0", + "v8flags": "^3.0.0", + "yn": "^2.0.0" + } }, - "useragent": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.2.1.tgz", - "integrity": "sha1-z1k+9PLRdYdei7ZY6pLhik/QbY4=", + "tsconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", + "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", "dev": true, "requires": { - "lru-cache": "2.2.x", - "tmp": "0.0.x" + "@types/strip-bom": "^3.0.0", + "@types/strip-json-comments": "0.0.30", + "strip-bom": "^3.0.0", + "strip-json-comments": "^2.0.0" }, "dependencies": { - "lru-cache": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz", - "integrity": "sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0=", + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true } } }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "tsickle": { + "version": "0.34.0", + "resolved": "https://registry.npmjs.org/tsickle/-/tsickle-0.34.0.tgz", + "integrity": "sha512-O3wCPRtL18Hc/ZBnaiKwmmjVzeCWTOTpsi0btfC7FWL3RnXpxLPxD6hoJ0QEXuSfG/0QJk+MWNjqT9N6fOyyIg==", "dev": true, "requires": { - "inherits": "2.0.3" + "minimist": "^1.2.0", + "mkdirp": "^0.5.1", + "source-map": "^0.7.3" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true - }, - "v8flags": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", - "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "tslint": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.11.0.tgz", + "integrity": "sha1-mPMMAurjzecAYgHkwzywi0hYHu0=", "dev": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.27.2" + }, + "dependencies": { + "resolve": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + } } }, - "validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "tsutils": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.8.0.tgz", + "integrity": "sha512-XQdPhgcoTbCD8baXC38PQ0vpTZ8T3YrE+vR66YIj/xvDt1//8iAhafpIT/4DmvzzC1QFapEImERu48Pa01dIUA==", "dev": true, "requires": { - "builtins": "^1.0.3" + "tslib": "^1.8.1" } }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "tty-browserify": { + "version": "0.0.0", + "resolved": "http://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", "dev": true }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - } + "safe-buffer": "^5.0.1" } }, - "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "dev": true, "requires": { - "indexof": "0.0.1" + "media-typer": "0.3.0", + "mime-types": "~2.1.18" } }, - "void-elements": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", - "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "vscode-uri": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.5.tgz", - "integrity": "sha1-O4majvccN/MFTXm9vdoxx7828g0=", + "typescript": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", + "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", "dev": true }, - "wait-on": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-3.0.1.tgz", - "integrity": "sha512-lZmX4gw2qgjEkobhe5lPEYAJZuV2erI31N1+vyzCgm3CdtrJv0karckpY5jKKyfaSrIPotUroQbN/pDaNC5d8w==", + "uglify-js": { + "version": "3.4.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz", + "integrity": "sha512-8CJsbKOtEbnJsTyv6LE6m6ZKniqMiFWmm9sRbopbkGs3gMPPfd3Fh8iIA4Ykv5MgaTbqHr4BaoGLJLZNhsrW1Q==", "dev": true, "requires": { - "core-js": "^2.5.7", - "joi": "^13.0.0", - "minimist": "^1.2.0", - "request": "^2.88.0", - "rx": "^4.1.0" + "commander": "~2.17.1", + "source-map": "~0.6.1" }, "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } }, - "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", - "dev": true, - "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-extendable": "^0.1.0" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + } + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", + "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "isarray": "1.0.0" } } } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + } + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "update-notifier": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", + "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "dev": true, + "requires": { + "boxen": "^1.2.1", + "chalk": "^2.0.1", + "configstore": "^3.0.0", + "import-lazy": "^2.1.0", + "is-ci": "^1.0.10", + "is-installed-globally": "^0.1.0", + "is-npm": "^1.0.0", + "latest-version": "^3.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "configstore": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", + "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } } } }, + "url-parse": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.4.tgz", + "integrity": "sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==", + "dev": true, + "requires": { + "querystringify": "^2.0.0", + "requires-port": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, + "v8flags": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.2.tgz", + "integrity": "sha512-MtivA7GF24yMPte9Rp/BWGCYQNaUj86zeYxV/x2RRJMKagImbbv3u8iJC57lNhWLPcGLJmHcHmFWkNsplbbLWw==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", + "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "dev": true, + "requires": { + "builtins": "^1.0.3" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "http://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, + "vscode-uri": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz", + "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==", + "dev": true + }, + "wait-on": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-3.2.0.tgz", + "integrity": "sha512-QUGNKlKLDyY6W/qHdxaRlXUAgLPe+3mLL/tRByHpRNcHs/c7dZXbu+OnJWGNux6tU1WFh/Z8aEwvbuzSAu79Zg==", + "dev": true, + "requires": { + "core-js": "^2.5.7", + "joi": "^13.0.0", + "minimist": "^1.2.0", + "request": "^2.88.0", + "rx": "^4.1.0" + } + }, + "watchpack": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", + "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "dev": true, + "requires": { + "chokidar": "^2.0.2", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + } + }, "wbuf": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", @@ -15259,9 +13072,9 @@ } }, "webdriver-js-extender": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.0.0.tgz", - "integrity": "sha512-fbyKiVu3azzIc5d4+26YfuPQcFTlgFQV5yQ/0OQj4Ybkl4g1YQuIPskf5v5wqwRJhHJnPHthB6tqCjWHOKLWag==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", + "integrity": "sha512-lcUKrjbBfCK6MNsh7xaY2UAUmZwe+/ib03AjVOpFobX4O7+83BUveSrLfU0Qsyb1DaKJdQRbuU+kM9aZ6QUhiQ==", "dev": true, "requires": { "@types/selenium-webdriver": "^3.0.0", @@ -15292,17 +13105,17 @@ } }, "webpack": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.23.1.tgz", - "integrity": "sha512-iE5Cu4rGEDk7ONRjisTOjVHv3dDtcFfwitSxT7evtYj/rANJpt1OuC/Kozh1pBa99AUBr1L/LsaNB+D9Xz3CEg==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.29.0.tgz", + "integrity": "sha512-pxdGG0keDBtamE1mNvT5zyBdx+7wkh6mh7uzMOo/uRQ/fhsdj5FXkh/j5mapzs060forql1oXqXN9HJGju+y7w==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.10", - "@webassemblyjs/helper-module-context": "1.7.10", - "@webassemblyjs/wasm-edit": "1.7.10", - "@webassemblyjs/wasm-parser": "1.7.10", - "acorn": "^5.6.2", - "acorn-dynamic-import": "^3.0.0", + "@webassemblyjs/ast": "1.7.11", + "@webassemblyjs/helper-module-context": "1.7.11", + "@webassemblyjs/wasm-edit": "1.7.11", + "@webassemblyjs/wasm-parser": "1.7.11", + "acorn": "^6.0.5", + "acorn-dynamic-import": "^4.0.0", "ajv": "^6.1.0", "ajv-keywords": "^3.1.0", "chrome-trace-event": "^1.0.0", @@ -15318,294 +13131,9 @@ "node-libs-browser": "^2.0.0", "schema-utils": "^0.4.4", "tapable": "^1.1.0", - "uglifyjs-webpack-plugin": "^1.2.4", + "terser-webpack-plugin": "^1.1.0", "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } + "webpack-sources": "^1.3.0" } }, "webpack-core": { @@ -15626,7 +13154,7 @@ }, "source-map": { "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", "dev": true, "requires": { @@ -15636,9 +13164,9 @@ } }, "webpack-dev-middleware": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz", - "integrity": "sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.5.1.tgz", + "integrity": "sha512-4dwCh/AyMOYAybggUr8fiCkRnjVDp+Cqlr9c+aaNB3GJYgRGYQWJ1YX/WAKUNA9dPNHZ6QSN2lYDKqjKSI8Vqw==", "dev": true, "requires": { "memory-fs": "~0.4.1", @@ -15656,9 +13184,9 @@ } }, "webpack-dev-server": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.10.tgz", - "integrity": "sha512-RqOAVjfqZJtQcB0LmrzJ5y4Jp78lv9CK0MZ1YJDTaTmedMZ9PU9FLMQNrMCfVu8hHzaVLVOJKBlGEHMN10z+ww==", + "version": "3.1.14", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz", + "integrity": "sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -15680,12 +13208,14 @@ "portfinder": "^1.0.9", "schema-utils": "^1.0.0", "selfsigned": "^1.9.1", + "semver": "^5.6.0", "serve-index": "^1.7.2", "sockjs": "0.3.19", "sockjs-client": "1.3.0", - "spdy": "^3.4.1", + "spdy": "^4.0.0", "strip-ansi": "^3.0.0", "supports-color": "^5.1.0", + "url": "^0.11.0", "webpack-dev-middleware": "3.4.0", "webpack-log": "^2.0.0", "yargs": "12.0.2" @@ -15697,78 +13227,12 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, "cliui": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", @@ -15814,13 +13278,13 @@ } }, "execa": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.10.0.tgz", - "integrity": "sha512-7XOMnz8Ynx1gGo/3hyV9loYNPWM94jG3+3T3Y8tsfSstFmETmENCMU/A/zj8Lyaj1lkgEepKepvd6240tBRvlw==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", "dev": true, "requires": { "cross-spawn": "^6.0.0", - "get-stream": "^3.0.0", + "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", @@ -15828,166 +13292,6 @@ "strip-eof": "^1.0.0" } }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "find-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", @@ -15997,25 +13301,13 @@ "locate-path": "^3.0.0" } }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "pump": "^3.0.0" } }, "invert-kv": { @@ -16024,88 +13316,12 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, "lcid": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", @@ -16125,53 +13341,27 @@ "path-exists": "^3.0.0" } }, - "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } + "mime": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", + "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "dev": true }, "os-locale": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.0.1.tgz", - "integrity": "sha512-7g5e7dmXPtzcP4bgsZ8ixDVqA7oWYuEz4lOSujeWyliPai4gfVDiFIcwBg3aGCPnmSGfzOKTK3ccPn0CKv3DBw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "execa": "^0.10.0", + "execa": "^1.0.0", "lcid": "^2.0.0", "mem": "^4.0.0" } }, "p-limit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", - "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz", + "integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -16192,6 +13382,16 @@ "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", @@ -16224,18 +13424,33 @@ } } }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "webpack-dev-middleware": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.4.0.tgz", + "integrity": "sha512-Q9Iyc0X9dP9bAsYskAVJ/hmIZZQwf/3Sy4xCAZgL5cUkjZmUZLt4l5HpbST/Pdgjn3u6pE7u5OdGd1apgzRujA==", + "dev": true, + "requires": { + "memory-fs": "~0.4.1", + "mime": "^2.3.1", + "range-parser": "^1.0.3", + "webpack-log": "^2.0.0" + } + }, "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true - }, "yargs": { "version": "12.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", @@ -16255,6 +13470,15 @@ "y18n": "^3.2.1 || ^4.0.0", "yargs-parser": "^10.1.0" } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } } } }, @@ -16269,9 +13493,9 @@ } }, "webpack-merge": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.4.tgz", - "integrity": "sha512-TmSe1HZKeOPey3oy1Ov2iS3guIZjWvMT2BBJDzzT5jScHTjVC3mpjJofgueEzaEd6ibhxRDD6MIblDr8tzh8iQ==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", + "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", "dev": true, "requires": { "lodash": "^4.17.5" @@ -16392,19 +13616,6 @@ } } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true, - "optional": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, "worker-farm": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", @@ -16415,9 +13626,9 @@ } }, "worker-loader": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-1.1.1.tgz", - "integrity": "sha512-qJZLVS/jMCBITDzPo/RuweYSIG8VJP5P67mP/71alGyTZRe1LYJFdwLjLalY3T5ifx0bMDRD3OB6P2p1escvlg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz", + "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==", "requires": { "loader-utils": "^1.0.0", "schema-utils": "^0.4.0" @@ -16425,7 +13636,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { @@ -16440,9 +13651,9 @@ "dev": true }, "write-file-atomic": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", - "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.2.tgz", + "integrity": "sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==", "dev": true, "requires": { "graceful-fs": "^4.1.11", @@ -16487,7 +13698,7 @@ }, "xmlbuilder": { "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", + "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=", "dev": true }, @@ -16504,9 +13715,9 @@ "dev": true }, "xregexp": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.2.0.tgz", - "integrity": "sha512-IyMa7SVe9FyT4WbQVW3b95mTLVceHhLEezQ02+QMvmIqDnKTxk0MLWIQPSW2MXAr1zQb+9yvwYhcyQULneh3wA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", + "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", "dev": true }, "xtend": { @@ -16568,25 +13779,24 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "dev": true - }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - } } } }, "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } } }, "yeast": { @@ -16601,10 +13811,24 @@ "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", "dev": true }, + "yup": { + "version": "0.26.10", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.26.10.tgz", + "integrity": "sha512-keuNEbNSnsOTOuGCt3UJW69jDE3O4P+UHAakO7vSeFMnjaitcmlbij/a3oNb9g1Y1KvSKH/7O1R2PQ4m4TRylw==", + "dev": true, + "requires": { + "@babel/runtime": "7.0.0", + "fn-name": "~2.0.1", + "lodash": "^4.17.10", + "property-expr": "^1.5.0", + "synchronous-promise": "^2.0.5", + "toposort": "^2.0.2" + } + }, "zone.js": { - "version": "0.8.26", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.26.tgz", - "integrity": "sha512-W9Nj+UmBJG251wkCacIkETgra4QgBo/vgoEkb4a2uoLzpQG7qF9nzwoLXWU5xj3Fg2mxGvEDh47mg24vXccYjA==" + "version": "0.8.29", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.8.29.tgz", + "integrity": "sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==" } } } diff --git a/package.json b/package.json index aa8f6abdd7..3279b484f8 100644 --- a/package.json +++ b/package.json @@ -1,104 +1,119 @@ { "name": "alfresco-content-app", - "version": "1.6.0", + "version": "1.7.0", "license": "LGPL-3.0", "scripts": { "ng": "ng", - "start": "ng serve --open", - "start:prod": "ng serve --prod --open", - "build": "node --max-old-space-size=8192 node_modules/@angular/cli/bin/ng build app --prod", - "build:dev": "ng build", - "build.e2e": "node --max-old-space-size=8192 node_modules/@angular/cli/bin/ng build app --configuration=e2e", + "start": "npm run build.extensions && ng serve --open", + "start:prod": "node --max-old-space-size=8192 node_modules/@angular/cli/bin/ng serve --prod --open", + "build:aos-extension": "npx rimraf dist/@alfresco/adf-office-services-ext && ng build adf-office-services-ext && cpr projects/adf-office-services-ext/ngi.json dist/@alfresco/adf-office-services-ext/ngi.json && cpr projects/adf-office-services-ext/assets dist/@alfresco/adf-office-services-ext/assets", + "build.extensions": "npm run build:aos-extension", + "build.app": "node --max-old-space-size=8192 node_modules/@angular/cli/bin/ng build app", + "build": "npm run build.extensions && npm run build.app -- --prod", + "build.e2e": "npm run build.extensions && npm run build.app -- --prod --configuration=e2e", "test": "ng test app --code-coverage", - "test:ci": "ng test app --code-coverage --watch=false", - "lint": "ng lint", + "test:ci": "npm run build.extensions && ng test adf-office-services-ext --watch=false && ng test app --code-coverage --watch=false", + "lint": "ng lint && npm run spellcheck && npm run format:check && npm run e2e.typecheck", "wd:update": "webdriver-manager update --gecko=false", + "e2e.typecheck": "tsc -p ./e2e/tsconfig.e2e.typecheck.json", "e2e": "npm run wd:update && protractor --baseUrl=http://localhost:4000", "e2e.local": "npm run wd:update && protractor --baseUrl=http://localhost:4200", - "start:docker": "docker-compose up -d --build && wait-on http://localhost:8080 && wait-on http://localhost:4000", + "wait:app": "wait-on http://localhost:8080 && wait-on http://localhost:4000", + "start:docker": "docker-compose up -d --build && npm run wait:app", "stop:docker": "docker-compose stop", "e2e:docker": "npm run start:docker && npm run e2e && npm run stop:docker", "spellcheck": "cspell 'src/**/*.ts' 'e2e/**/*.ts' 'projects/**/*.ts'", "inspect.bundle": "ng build app --prod --stats-json && npx webpack-bundle-analyzer dist/app/stats.json", - "format:check": "prettier --list-different \"src/{app,environments}/**/*{.ts,.js,.css,.scss}\"", - "build.tomcat": "npm run build -- --base-href ./ && jar -cvf docker/tomcat/artifacts/content-app.war -C dist/app/ .", + "format:check": "prettier --check \"src/{app,environments}/**/*.{ts,js,css,scss,html}\"", + "format:fix": "prettier --write \"src/{app,environments}/**/*.{ts,js,css,scss,html}\"", + "build.tomcat": "npm run build.extensions && npm run build.app -- --prod --base-href ./ && jar -cvf docker/tomcat/artifacts/content-app.war -C dist/app/ .", "build.tomcat.e2e": "./build-tomcat-e2e.sh", "e2e.tomcat": "npm run wd:update && protractor --baseUrl=http://localhost:4000/content-app/", - "docker.tomcat.start": "cd docker/tomcat && docker-compose up -d --build && wait-on http://localhost:8080 && wait-on http://localhost:4000", + "docker.tomcat.start": "cd docker/tomcat && docker-compose up -d --build && npm run wait:app", "docker.tomcat.stop": "cd docker/tomcat && docker-compose stop", - "docker.tomcat.e2e": "npm run docker.tomcat.start && npm run e2e.tomcat" + "docker.tomcat.e2e": "npm run docker.tomcat.start && npm run e2e.tomcat", + "lint:staged": "lint-staged" }, "private": true, "dependencies": { - "@alfresco/adf-content-services": "2.6.1", - "@alfresco/adf-core": "2.6.1", - "@alfresco/adf-extensions": "3.0.0-383b74151a47e188020249aea7ec0dfb586bd0b6", - "@angular/animations": "7.1.1", - "@angular/cdk": "^7.1.0", - "@angular/common": "7.1.1", - "@angular/compiler": "7.1.1", - "@angular/core": "7.1.1", - "@angular/flex-layout": "^7.0.0-beta.19", - "@angular/forms": "7.1.1", - "@angular/http": "7.1.1", - "@angular/material": "^7.1.0", - "@angular/material-moment-adapter": "^7.1.0", - "@angular/platform-browser": "7.1.1", - "@angular/platform-browser-dynamic": "7.1.1", - "@angular/router": "7.1.1", - "@mat-datetimepicker/core": "^2.0.1", - "@mat-datetimepicker/moment": "^2.0.1", - "@ngrx/effects": "^6.1.2", - "@ngrx/router-store": "^6.1.2", - "@ngrx/store": "^6.1.2", - "@ngrx/store-devtools": "^6.1.2", - "@ngx-translate/core": "^10.0.2", - "alfresco-js-api": "2.6.1", + "@alfresco/adf-content-services": "3.0.0", + "@alfresco/adf-core": "3.0.0", + "@alfresco/adf-extensions": "3.0.0", + "@alfresco/js-api": "3.0.0", + "@angular/animations": "7.2.7", + "@angular/cdk": "^7.3.3", + "@angular/common": "7.2.7", + "@angular/compiler": "7.2.7", + "@angular/core": "7.2.7", + "@angular/flex-layout": "^7.0.0-beta.23", + "@angular/forms": "7.2.7", + "@angular/http": "7.2.7", + "@angular/material": "^7.3.3", + "@angular/material-moment-adapter": "^7.3.3", + "@angular/platform-browser": "7.2.7", + "@angular/platform-browser-dynamic": "7.2.7", + "@angular/router": "7.2.7", + "@mat-datetimepicker/core": "^3.0.0-beta.0", + "@mat-datetimepicker/moment": "^3.0.0-beta.0", + "@ngrx/effects": "^7.3.0", + "@ngrx/router-store": "^7.3.0", + "@ngrx/store": "^7.3.0", + "@ngrx/store-devtools": "^7.3.0", + "@ngx-translate/core": "^11.0.1", "core-js": "^2.5.7", "hammerjs": "2.0.8", "minimatch-browser": "^1.0.0", - "moment": "^2.22.2", + "moment": "^2.24.0", "moment-es6": "1.0.0", "pdfjs-dist": "^2.0.489", - "rxjs": "^6.3.3", - "zone.js": "0.8.26" + "rxjs": "^6.4.0", + "zone.js": "0.8.29" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.11.0", - "@angular-devkit/build-ng-packagr": "~0.11.0", - "@angular/cli": "^7.1.0", - "@angular/compiler-cli": "7.1.1", - "@angular/language-service": "7.1.1", + "@angular-devkit/build-angular": "~0.13.0", + "@angular-devkit/build-ng-packagr": "~0.13.0", + "@angular/cli": "^7.3.4", + "@angular/compiler-cli": "7.2.7", + "@angular/language-service": "7.2.7", "@types/jasmine": "^2.5.53", "@types/jasminewd2": "^2.0.2", "@types/node": "9.3.0", "@types/selenium-webdriver": "^3.0.8", - "alfresco-js-api-node": "^2.6.0", "chrome-remote-interface": "^0.26.1", "codelyzer": "^4.5.0", + "cpr": "^3.0.1", "cspell": "^3.1.3", "jasmine-core": "~2.8.0", "jasmine-reporters": "^2.2.1", "jasmine-spec-reporter": "~4.2.1", - "jasmine2-protractor-utils": "^1.3.0", "jasminewd2": "^2.2.0", - "karma": "^3.0.0", + "karma": "^4.0.0", "karma-chrome-launcher": "~2.2.0", "karma-cli": "~1.0.1", - "karma-coverage-istanbul-reporter": "^1.2.1", + "karma-coverage-istanbul-reporter": "^2.0.4", "karma-jasmine": "~1.1.0", "karma-jasmine-html-reporter": "^0.2.2", - "ng-packagr": "^4.4.0", - "prettier": "^1.15.2", + "lint-staged": "^8.1.4", + "ng-packagr": "^4.7.0", + "node-stream-zip": "1.8.0", + "pre-commit": "^1.2.2", + "prettier": "^1.16.0", "protractor": "^5.4.0", + "protractor-screenshoter-plugin": "0.10.3", "rimraf": "2.6.2", - "rxjs-tslint-rules": "^4.11.0", + "rxjs-tslint-rules": "^4.16.1", "selenium-webdriver": "4.0.0-alpha.1", "ts-node": "~4.1.0", - "tsickle": "0.33.1", + "tsickle": "0.34.0", "tslib": "^1.9.0", "tslint": "~5.11.0", - "typescript": "^3.1.6", + "typescript": "3.2.4", "wait-on": "^3.0.1" - } + }, + "lint-staged": { + "*.{ts,js,css,scss,html}": [ + "prettier --single-quote --write" + ] + }, + "pre-commit": "lint:staged" } diff --git a/projects/adf-office-services-ext/LICENSE b/projects/adf-office-services-ext/LICENSE new file mode 100644 index 0000000000..430d42bbea --- /dev/null +++ b/projects/adf-office-services-ext/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/projects/adf-office-services-ext/README.md b/projects/adf-office-services-ext/README.md new file mode 100644 index 0000000000..f8f8cb161e --- /dev/null +++ b/projects/adf-office-services-ext/README.md @@ -0,0 +1,72 @@ +# Alfresco Office Services Extension + +An extension module for the Alfresco Content Application that enables "Edit in Microsoft Office" feature. + +Integrates with: + +- Context Menus +- Toolbars +- Viewer / Open With + +## Automated Installation + +Install the `ngi` as a global tool: + +```sh +npm i -g @ngstack/install +``` + +In the project root: + +```sh +ngi @alfresco/adf-office-services-ext --module=extensions +``` + +Update `app.extensions.json` and append a reference to the plugin definition: + +```json +{ + "$references": ["aos.plugin.json"] +} +``` + +## Manual Installation + +Install the extension library + +```sh +npm i @alfresco/adf-office-services-ext +``` + +Update the `extensions.module.ts` and import corresponding module. + +```ts +import { NgModule } from '@angular/core'; +import { AosExtensionModule } from '@alfresco/adf-office-services-ext'; + +// Main entry point for external extensions only. +// For any application-specific code use CoreExtensionsModule instead. + +@NgModule({ + imports: [AosExtensionModule] +}) +export class AppExtensionsModule {} +``` + +Setup the resource references in the `angular.json` assets section: + +```json +{ + "glob": "**/*.json", + "input": "node_modules/@alfresco/adf-office-services-ext/assets", + "output": "./assets/plugins" +} +``` + +Update `app.extensions.json` and append a reference to the plugin definition: + +```json +{ + "$references": ["aos.plugin.json"] +} +``` diff --git a/projects/adf-office-services-ext/assets/aos.plugin.json b/projects/adf-office-services-ext/assets/aos.plugin.json new file mode 100644 index 0000000000..3a903057cc --- /dev/null +++ b/projects/adf-office-services-ext/assets/aos.plugin.json @@ -0,0 +1,75 @@ +{ + "$schema": "../../../extension.schema.json", + "$id": "9a635542-d87a-4558-ae64-ffa199d1a364", + "$version": "0.0.6", + "$name": "keensoft.aos.plugin", + "$description": "Extension that provides Office Edit Online Action", + "$vendor": "Keensoft", + "$license": "Apache-2.0", + "$runtime": "1.6.0", + + "actions": [ + { + "id": "aos.openWith.office", + "type": "AOS_ACTION", + "payload": "$(context.selection.first.entry)" + } + ], + + "features": { + "toolbar": [ + { + "id": "app.toolbar.more", + "children": [ + { + "id": "aos.toolbar.openWith.office", + "order": 90, + "icon": "edit", + "title": "AOS.ACTION_TITLE", + "actions": { + "click": "aos.openWith.office" + }, + "rules": { + "visible": "aos.canOpenWithOffice" + } + } + ] + } + ], + "contextMenu": [ + { + "id": "aos.context.openWith.office", + "order": 90, + "icon": "edit", + "title": "AOS.ACTION_TITLE", + "actions": { + "click": "aos.openWith.office" + }, + "rules": { + "visible": "aos.canOpenWithOffice" + } + } + ], + "viewer": { + "toolbarActions": [ + { + "id": "app.viewer.toolbar.more", + "children": [ + { + "id": "aos.viewer.openWith.office", + "order": 1, + "icon": "edit", + "title": "AOS.ACTION_TITLE", + "actions": { + "click": "aos.openWith.office" + }, + "rules": { + "visible": "aos.canOpenWithOffice" + } + } + ] + } + ] + } + } +} diff --git a/projects/adf-office-services-ext/assets/i18n/ar.json b/projects/adf-office-services-ext/assets/i18n/ar.json new file mode 100644 index 0000000000..f90e4fd3cb --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/ar.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "تحرير في ™Microsoft Office" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/cs.json b/projects/adf-office-services-ext/assets/i18n/cs.json new file mode 100644 index 0000000000..a610b42556 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/cs.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Upraveno v: Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/da.json b/projects/adf-office-services-ext/assets/i18n/da.json new file mode 100644 index 0000000000..2b70dcea87 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/da.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Rediger i Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/de.json b/projects/adf-office-services-ext/assets/i18n/de.json new file mode 100644 index 0000000000..60c7ab3647 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/de.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "In Microsoft Office™ bearbeiten" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/en.json b/projects/adf-office-services-ext/assets/i18n/en.json new file mode 100644 index 0000000000..9d146cb187 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/en.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Edit in Microsoft Office™" + } +} diff --git a/projects/adf-office-services-ext/assets/i18n/es.json b/projects/adf-office-services-ext/assets/i18n/es.json new file mode 100644 index 0000000000..bc1cc47ccd --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/es.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Editar en Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/fi.json b/projects/adf-office-services-ext/assets/i18n/fi.json new file mode 100644 index 0000000000..d7d02e157e --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/fi.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Muokkaa Microsoft Office™ -sovelluksessa" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/fr.json b/projects/adf-office-services-ext/assets/i18n/fr.json new file mode 100644 index 0000000000..4b6b00426e --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/fr.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Modifier dans Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/it.json b/projects/adf-office-services-ext/assets/i18n/it.json new file mode 100644 index 0000000000..786872007c --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/it.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Modifica in Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/ja.json b/projects/adf-office-services-ext/assets/i18n/ja.json new file mode 100644 index 0000000000..f4a9682a4c --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/ja.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Microsoft Office™ で編集" + } +} diff --git a/projects/adf-office-services-ext/assets/i18n/nb.json b/projects/adf-office-services-ext/assets/i18n/nb.json new file mode 100644 index 0000000000..bcea6a8501 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/nb.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Rediger i Microsoft Office™" + } +} diff --git a/projects/adf-office-services-ext/assets/i18n/nl.json b/projects/adf-office-services-ext/assets/i18n/nl.json new file mode 100644 index 0000000000..e39352a996 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/nl.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Bewerken in Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/pl.json b/projects/adf-office-services-ext/assets/i18n/pl.json new file mode 100644 index 0000000000..01b41c5486 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/pl.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Edytuj w programie Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/pt-BR.json b/projects/adf-office-services-ext/assets/i18n/pt-BR.json new file mode 100644 index 0000000000..0e7be5db37 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/pt-BR.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Editar no Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/ru.json b/projects/adf-office-services-ext/assets/i18n/ru.json new file mode 100644 index 0000000000..6d941a37bc --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/ru.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Редактировать в Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/sv.json b/projects/adf-office-services-ext/assets/i18n/sv.json new file mode 100644 index 0000000000..4d1662e2a1 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/sv.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "Redigera i Microsoft Office™" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/assets/i18n/zh-CN.json b/projects/adf-office-services-ext/assets/i18n/zh-CN.json new file mode 100644 index 0000000000..a5df579693 --- /dev/null +++ b/projects/adf-office-services-ext/assets/i18n/zh-CN.json @@ -0,0 +1,5 @@ +{ + "AOS": { + "ACTION_TITLE": "在 Microsoft Office™ 中编辑" + } +} \ No newline at end of file diff --git a/projects/adf-office-services-ext/karma.conf.js b/projects/adf-office-services-ext/karma.conf.js new file mode 100644 index 0000000000..dd9b7e664d --- /dev/null +++ b/projects/adf-office-services-ext/karma.conf.js @@ -0,0 +1,34 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function(config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage-istanbul-reporter'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + coverageIstanbulReporter: { + dir: require('path').join( + __dirname, + '../../coverage/adf-office-services-ext' + ), + reports: ['html', 'lcovonly'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); +}; diff --git a/projects/adf-office-services-ext/ng-package.json b/projects/adf-office-services-ext/ng-package.json new file mode 100644 index 0000000000..c63ea38c6f --- /dev/null +++ b/projects/adf-office-services-ext/ng-package.json @@ -0,0 +1,14 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/@alfresco/adf-office-services-ext", + "lib": { + "entryFile": "src/public_api.ts", + "flatModuleFile": "adf-office-services-ext", + "umdModuleIds": { + "@alfresco/js-api": "@alfresco/js-api", + "@alfresco/adf-core": "@alfresco/adf-core", + "@alfresco/adf-extensions": "@alfresco/adf-extensions", + "@ngrx/effects": "@ngrx/effects" + } + } +} diff --git a/projects/adf-office-services-ext/ngi.json b/projects/adf-office-services-ext/ngi.json new file mode 100644 index 0000000000..edb04a010a --- /dev/null +++ b/projects/adf-office-services-ext/ngi.json @@ -0,0 +1,20 @@ +{ + "assets": [ + { + "glob": "**/*", + "input": "./assets", + "output": "./assets/adf-office-services-ext" + }, + { + "glob": "aos.plugin.json", + "input": "./assets", + "output": "./assets/plugins" + } + ], + "modules": [ + { + "name": "AosExtensionModule", + "namespace": "@alfresco/adf-office-services-ext" + } + ] +} diff --git a/projects/adf-office-services-ext/package.json b/projects/adf-office-services-ext/package.json new file mode 100644 index 0000000000..849fd06b6e --- /dev/null +++ b/projects/adf-office-services-ext/package.json @@ -0,0 +1,26 @@ +{ + "name": "@alfresco/adf-office-services-ext", + "version": "0.0.6", + "license": "Apache-2.0", + "author": { + "name": "Keensoft", + "url": "http://www.keensoft.es/en/" + }, + "contributors": [ + { + "name": "Denys Vuika", + "email": "denys.vuka@gmail.com", + "url": "https://medium.com/@denysvuika" + } + ], + "homepage": "https://github.com/Alfresco/alfresco-content-app", + "keywords": ["Alfresco", "ADF", "ACA", "Content Application"], + "peerDependencies": { + "@angular/common": "^7.2.0", + "@angular/core": "^7.2.0", + "@ngrx/effects": "^7.2.0", + "@ngrx/store": "^7.2.0", + "@alfresco/adf-extensions": "^3.0.0", + "@alfresco/js-api": "^3.0.0" + } +} diff --git a/projects/adf-office-services-ext/src/lib/actions/aos.actions.ts b/projects/adf-office-services-ext/src/lib/actions/aos.actions.ts new file mode 100755 index 0000000000..1a3bd37a0a --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/actions/aos.actions.ts @@ -0,0 +1,9 @@ +import { Action } from '@ngrx/store'; +import { MinimalNodeEntryEntity } from '@alfresco/js-api'; + +export const AOS_ACTION = 'AOS_ACTION'; + +export class AosAction implements Action { + readonly type = AOS_ACTION; + constructor(public payload: MinimalNodeEntryEntity) {} +} diff --git a/projects/adf-office-services-ext/src/lib/aos-extension.module.ts b/projects/adf-office-services-ext/src/lib/aos-extension.module.ts new file mode 100644 index 0000000000..baafa69c44 --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/aos-extension.module.ts @@ -0,0 +1,25 @@ +import { ExtensionService } from '@alfresco/adf-extensions'; +import { NgModule } from '@angular/core'; +import { EffectsModule } from '@ngrx/effects'; + +import { AosEditOnlineService } from './aos-extension.service'; +import { AosEffects } from './effects/aos.effects'; + +import { canOpenWithOffice } from './evaluators'; +import { TranslationService } from '@alfresco/adf-core'; + +@NgModule({ + imports: [EffectsModule.forFeature([AosEffects])], + providers: [AosEditOnlineService] +}) +export class AosExtensionModule { + constructor(extensions: ExtensionService, translation: TranslationService) { + translation.addTranslationFolder( + 'adf-office-services-ext', + 'assets/adf-office-services-ext' + ); + extensions.setEvaluators({ + 'aos.canOpenWithOffice': canOpenWithOffice + }); + } +} diff --git a/projects/adf-office-services-ext/src/lib/aos-extension.service.ts b/projects/adf-office-services-ext/src/lib/aos-extension.service.ts new file mode 100644 index 0000000000..04ff47135a --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/aos-extension.service.ts @@ -0,0 +1,129 @@ +/* cspell:disable */ +import { + AppConfigService, + AuthenticationService, + NotificationService, + AlfrescoApiService +} from '@alfresco/adf-core'; +import { Injectable } from '@angular/core'; +import { MinimalNodeEntryEntity } from '@alfresco/js-api'; +import { supportedExtensions, getFileExtension } from './utils'; + +@Injectable({ + providedIn: 'root' +}) +export class AosEditOnlineService { + constructor( + private alfrescoAuthenticationService: AuthenticationService, + private appConfigService: AppConfigService, + private notificationService: NotificationService, + private apiService: AlfrescoApiService + ) {} + + onActionEditOnlineAos(node: MinimalNodeEntryEntity): void { + if (node && node.isFile && node.properties) { + if (node.isLocked) { + // const checkedOut = node.aspectNames.find( + // (aspect: string) => aspect === 'cm:checkedOut' + // ); + const checkedOut = + node.properties['cm:lockType'] === 'WRITE_LOCK' || + node.properties['cm:lockType'] === 'READ_ONLY_LOCK'; + const lockOwner = node.properties['cm:lockOwner']; + const differentLockOwner = + lockOwner.id !== this.alfrescoAuthenticationService.getEcmUsername(); + + if (checkedOut && differentLockOwner) { + this.onAlreadyLockedNotification(node.id, lockOwner); + } else { + this.triggerEditOnlineAos(node); + } + } else { + this.triggerEditOnlineAos(node); + } + } + } + + private getUserAgent(): string { + return navigator.userAgent.toLowerCase(); + } + + private isWindows(): boolean { + return this.getUserAgent().indexOf('win') !== -1 ? true : false; + } + + private isMacOs(): boolean { + return this.getUserAgent().indexOf('mac') !== -1 ? true : false; + } + + private onAlreadyLockedNotification(nodeId: string, lockOwner: string) { + this.notificationService.openSnackMessage( + `Document {nodeId} locked by {lockOwner}`, + 3000 + ); + } + + private getProtocolForFileExtension(fileExtension: string) { + return supportedExtensions[fileExtension]; + } + + private triggerEditOnlineAos(node: MinimalNodeEntryEntity): void { + const aosHost = this.appConfigService.get('aosHost'); + const url = `${aosHost}/_aos_nodeid/${node.id}/${encodeURIComponent( + node.name + )}`; + const fileExtension = getFileExtension(node.name); + const protocolHandler = this.getProtocolForFileExtension(fileExtension); + + if (protocolHandler === undefined) { + this.notificationService.openSnackMessage( + `No protocol handler found for {fileExtension}`, + 3000 + ); + return; + } + + if (!this.isWindows() && !this.isMacOs()) { + this.notificationService.openSnackMessage( + 'Only supported for Windows and Mac', + 3000 + ); + } else { + this.apiService.nodesApi + .lockNode(node.id, { + type: 'ALLOW_OWNER_CHANGES', + lifetime: 'PERSISTENT' + }) + .then( + () => { + this.aos_tryToLaunchOfficeByMsProtocolHandler(protocolHandler, url); + }, + () => { + this.notificationService.openSnackMessage( + 'Cannot lock the node for editing.', + 3000 + ); + } + ); + } + } + + private aos_tryToLaunchOfficeByMsProtocolHandler( + protocolHandler: string, + url: string + ) { + const protocolUrl = protocolHandler + ':ofe%7Cu%7C' + url; + + const iframe = document.createElement('iframe'); + iframe.style.display = 'none'; + iframe.src = protocolUrl; + + document.body.appendChild(iframe); + + setTimeout(() => { + if (iframe) { + document.body.removeChild(iframe); + } + }, 500); + } +} diff --git a/projects/adf-office-services-ext/src/lib/effects/aos.effects.ts b/projects/adf-office-services-ext/src/lib/effects/aos.effects.ts new file mode 100755 index 0000000000..b2fee28429 --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/effects/aos.effects.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { Actions, Effect, ofType } from '@ngrx/effects'; +import { map } from 'rxjs/operators'; + +import { AOS_ACTION, AosAction } from '../actions/aos.actions'; +import { AosEditOnlineService } from '../aos-extension.service'; + +@Injectable() +export class AosEffects { + constructor( + private actions$: Actions, + private aosEditOnlineService: AosEditOnlineService + ) {} + + @Effect({ dispatch: false }) + openOffice$ = this.actions$.pipe( + ofType(AOS_ACTION), + map(action => { + if (action.payload) { + this.aosEditOnlineService.onActionEditOnlineAos(action.payload); + } + }) + ); +} diff --git a/projects/adf-office-services-ext/src/lib/evaluators.spec.ts b/projects/adf-office-services-ext/src/lib/evaluators.spec.ts new file mode 100644 index 0000000000..e38843a5f7 --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/evaluators.spec.ts @@ -0,0 +1,230 @@ +import { canOpenWithOffice } from './evaluators'; + +describe('evaluators', () => { + describe('canOpenWithOffice', () => { + it('should return [false] if using SSO', () => { + const context: any = { + auth: { + isOauth() { + return true; + } + } + }; + + expect(canOpenWithOffice(context, null)).toBeFalsy(); + }); + + it('should return [false] if no selection present', () => { + const context: any = { + selection: null + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if no file selected', () => { + const context: any = { + selection: { + file: null + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if selected file has no entry', () => { + const context: any = { + selection: { + file: { + entry: null + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if selected file has no properties', () => { + const context: any = { + selection: { + file: { + entry: { + properties: null + } + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if selected file is locked', () => { + const context: any = { + selection: { + file: { + entry: { + isLocked: true, + properties: {} + } + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if selected file has no extension', () => { + const context: any = { + selection: { + file: { + entry: { + name: 'readme', + isLocked: false, + properties: {} + } + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if extension is not supported', () => { + const context: any = { + selection: { + file: { + entry: { + name: 'run.exe', + isLocked: false, + properties: {} + } + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if selected file has write lock', () => { + const context: any = { + selection: { + file: { + entry: { + name: 'document.docx', + isLocked: false, + properties: { + 'cm:lockType': 'WRITE_LOCK' + } + } + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if selected file has read-only lock', () => { + const context: any = { + selection: { + file: { + entry: { + name: 'document.docx', + isLocked: false, + properties: { + 'cm:lockType': 'READ_ONLY_LOCK' + } + } + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if current user is not lock owner', () => { + const context: any = { + profile: { + id: 'user1' + }, + selection: { + file: { + entry: { + name: 'document.docx', + isLocked: false, + properties: { + 'cm:lockType': 'READ_ONLY_LOCK', + 'cm:lockOwner': { + id: 'user2' + } + } + } + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if current user is lock owner', () => { + const context: any = { + profile: { + id: 'user1' + }, + selection: { + file: { + entry: { + name: 'document.docx', + isLocked: false, + properties: { + 'cm:lockType': 'READ_ONLY_LOCK', + 'cm:lockOwner': { + id: 'user1' + } + } + } + } + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [false] if permissions check is false', () => { + const context: any = { + selection: { + file: { + entry: { + name: 'document.docx', + isLocked: false, + properties: {} + } + } + }, + permissions: { + check: () => false + } + }; + + expect(canOpenWithOffice(context)).toBeFalsy(); + }); + + it('should return [true] if all checks succeed', () => { + const context: any = { + selection: { + file: { + entry: { + name: 'document.docx', + isLocked: false, + properties: {} + } + } + }, + permissions: { + check: () => true + } + }; + + expect(canOpenWithOffice(context)).toBeTruthy(); + }); + }); +}); diff --git a/projects/adf-office-services-ext/src/lib/evaluators.ts b/projects/adf-office-services-ext/src/lib/evaluators.ts new file mode 100644 index 0000000000..037df58511 --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/evaluators.ts @@ -0,0 +1,84 @@ +import { RuleContext, RuleParameter } from '@alfresco/adf-extensions'; +import { AuthenticationService } from '@alfresco/adf-core'; +import { getFileExtension, supportedExtensions } from './utils'; + +export function canOpenWithOffice( + context: RuleContext, + ...args: RuleParameter[] +): boolean { + if ( + context.navigation && + context.navigation.url && + context.navigation.url.startsWith('/trashcan') + ) { + return false; + } + + // todo: needs to have typed access via SDK (1.8) + const auth: AuthenticationService = (context).auth; + if (auth && auth.isOauth()) { + return false; + } + + if (!context || !context.selection) { + return false; + } + + const { file } = context.selection; + + if (!file || !file.entry) { + return false; + } + + const extension = getFileExtension(file.entry.name); + if (!extension || !supportedExtensions[extension]) { + return false; + } + + // workaround for Shared files + if ( + context.navigation && + context.navigation.url && + context.navigation.url.startsWith('/shared') + ) { + if (file.entry.hasOwnProperty('allowableOperationsOnTarget')) { + return context.permissions.check(file, ['update'], { + target: 'allowableOperationsOnTarget' + }); + } + } + + if (!file.entry.properties) { + return false; + } + + if (file.entry.isLocked) { + return false; + } + + /* + if (file.entry && file.entry.aspectNames) { + const checkedOut = file.entry.aspectNames.find( + (aspect: string) => aspect === 'cm:checkedOut' + ); + + if (checkedOut) { + return false; + } + } + */ + + if ( + file.entry.properties['cm:lockType'] === 'WRITE_LOCK' || + file.entry.properties['cm:lockType'] === 'READ_ONLY_LOCK' + ) { + return false; + } + + const lockOwner = file.entry.properties['cm:lockOwner']; + if (lockOwner && lockOwner.id !== context.profile.id) { + return false; + } + + return context.permissions.check(file, ['update']); +} diff --git a/projects/adf-office-services-ext/src/lib/utils.spec.ts b/projects/adf-office-services-ext/src/lib/utils.spec.ts new file mode 100644 index 0000000000..cd0a905f73 --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/utils.spec.ts @@ -0,0 +1,15 @@ +import { getFileExtension } from './utils'; + +describe('utils', () => { + it('should return no extension when input is null', () => { + expect(getFileExtension(null)).toBe(null); + }); + + it('should extract file extension', () => { + expect(getFileExtension('test.docx')).toBe('docx'); + }); + + it('should not extract file extension', () => { + expect(getFileExtension('unknown')).toBe(null); + }); +}); diff --git a/projects/adf-office-services-ext/src/lib/utils.ts b/projects/adf-office-services-ext/src/lib/utils.ts new file mode 100644 index 0000000000..43bfa0684f --- /dev/null +++ b/projects/adf-office-services-ext/src/lib/utils.ts @@ -0,0 +1,37 @@ +/* cspell:disable */ +export const supportedExtensions = { + doc: 'ms-word', + docx: 'ms-word', + docm: 'ms-word', + dot: 'ms-word', + dotx: 'ms-word', + dotm: 'ms-word', + xls: 'ms-excel', + xlsx: 'ms-excel', + xlsb: 'ms-excel', + xlsm: 'ms-excel', + xlt: 'ms-excel', + xltx: 'ms-excel', + xltm: 'ms-excel', + ppt: 'ms-powerpoint', + pptx: 'ms-powerpoint', + pot: 'ms-powerpoint', + potx: 'ms-powerpoint', + potm: 'ms-powerpoint', + pptm: 'ms-powerpoint', + pps: 'ms-powerpoint', + ppsx: 'ms-powerpoint', + ppam: 'ms-powerpoint', + ppsm: 'ms-powerpoint', + sldx: 'ms-powerpoint', + sldm: 'ms-powerpoint' +}; +/* cspell:enable */ + +export function getFileExtension(fileName: string): string { + if (fileName) { + const match = fileName.match(/\.([^\./\?\#]+)($|\?|\#)/); + return match ? match[1] : null; + } + return null; +} diff --git a/projects/adf-office-services-ext/src/public_api.ts b/projects/adf-office-services-ext/src/public_api.ts new file mode 100644 index 0000000000..af56fbcbee --- /dev/null +++ b/projects/adf-office-services-ext/src/public_api.ts @@ -0,0 +1,5 @@ +export * from './lib/aos-extension.service'; +export * from './lib/actions/aos.actions'; +export * from './lib/effects/aos.effects'; + +export * from './lib/aos-extension.module'; diff --git a/projects/adf-office-services-ext/src/test.ts b/projects/adf-office-services-ext/src/test.ts new file mode 100644 index 0000000000..e11ff1c97b --- /dev/null +++ b/projects/adf-office-services-ext/src/test.ts @@ -0,0 +1,22 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; +import 'zone.js/dist/zone-testing'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +declare const require: any; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); diff --git a/projects/adf-office-services-ext/tsconfig.lib.json b/projects/adf-office-services-ext/tsconfig.lib.json new file mode 100644 index 0000000000..3fe337fcf5 --- /dev/null +++ b/projects/adf-office-services-ext/tsconfig.lib.json @@ -0,0 +1,32 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/lib", + "target": "es2015", + "module": "es2015", + "moduleResolution": "node", + "declaration": true, + "sourceMap": true, + "inlineSources": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": true, + "types": [], + "lib": [ + "dom", + "es2018" + ] + }, + "angularCompilerOptions": { + "annotateForClosureCompiler": true, + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "fullTemplateTypeCheck": true, + "strictInjectionParameters": true, + "enableResourceInlining": true + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/projects/adf-office-services-ext/tsconfig.spec.json b/projects/adf-office-services-ext/tsconfig.spec.json new file mode 100644 index 0000000000..16da33db07 --- /dev/null +++ b/projects/adf-office-services-ext/tsconfig.spec.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "src/test.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/projects/adf-office-services-ext/tslint.json b/projects/adf-office-services-ext/tslint.json new file mode 100644 index 0000000000..124133f849 --- /dev/null +++ b/projects/adf-office-services-ext/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "lib", + "camelCase" + ], + "component-selector": [ + true, + "element", + "lib", + "kebab-case" + ] + } +} diff --git a/protractor.conf.js b/protractor.conf.js index 336b17908c..91c0e5d325 100755 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -2,9 +2,7 @@ // https://github.com/angular/protractor/blob/master/lib/config.ts const path = require('path'); -const { - SpecReporter -} = require('jasmine-spec-reporter'); +const { SpecReporter } = require('jasmine-spec-reporter'); const jasmineReporters = require('jasmine-reporters'); const CDP = require('chrome-remote-interface'); @@ -52,6 +50,7 @@ exports.config = { ], SELENIUM_PROMISE_MANAGER: true, + capabilities: { browserName: 'chrome', chromeOptions: { @@ -62,7 +61,13 @@ exports.config = { default_directory: downloadFolder } }, - args: ['--incognito', '--headless', '--remote-debugging-port=9222', '--disable-gpu', '--no-sandbox'] + args: [ + '--incognito', + '--headless', + '--remote-debugging-port=9222', + '--disable-gpu', + '--no-sandbox' + ] } }, @@ -71,23 +76,27 @@ exports.config = { // baseUrl: 'http://localhost:4000', getPageTimeout: 50000, - framework: 'jasmine2', + framework: 'jasmine', jasmineNodeOpts: { showColors: true, defaultTimeoutInterval: 60000, - print: function () {} + print: function() {} }, - plugins: [{ - package: 'jasmine2-protractor-utils', - disableHTMLReport: false, - disableScreenshot: false, - screenshotOnExpectFailure: true, - screenshotOnSpecFailure: false, - clearFoldersBeforeTest: true, - htmlReportDir: `${projectRoot}/e2e-output/html-report/`, - screenshotPath: `${projectRoot}/e2e-output/screenshots/` - }], + plugins: [ + { + package: 'protractor-screenshoter-plugin', + screenshotPath: `${projectRoot}/e2e-output/report`, + screenshotOnExpect: 'failure', + screenshotOnSpec: 'none', + withLogs: true, + writeReportFreq: 'end', + imageToAscii: 'none', + htmlOnExpect: 'none', + htmlOnSpec: 'none', + clearFoldersBeforeTest: true + } + ], onPrepare() { require('ts-node').register({ @@ -102,7 +111,8 @@ exports.config = { jasmine.getEnv().addReporter( new SpecReporter({ spec: { - displayStacktrace: true + displayStacktrace: true, + displayDuration: true } }) ); diff --git a/scripts/update-version.sh b/scripts/update-version.sh index 6c03c0d3d0..22d0762c30 100755 --- a/scripts/update-version.sh +++ b/scripts/update-version.sh @@ -1,104 +1,45 @@ #!/usr/bin/env bash DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -eval JS_API=true eval GNU=false -eval EXEC_COMPONENT=true -eval DIFFERENT_JS_API=false -eval AUTO=false -eval libs=( "core" - "content-services" - "extensions" - #"process-services" - #"insights" +eval libs=( "@alfresco/adf-core" + "@alfresco/adf-content-services" + "@alfresco/adf-extensions" + "@alfresco/js-api" ) cd ${DIR}/.. -prefix="@alfresco/adf-" - show_help() { - echo "Usage: update-version.sh" + echo "Usage: update-version.sh -v latest" echo "" - echo "-sj or -sjsapi don't update js-api version" - echo "-vj or -versionjsapi to use a different version of js-api" - echo "-v or -version version to update" - echo "-alpha update last alpha version of js-api and lib automatically" - echo "-beta update beta alpha version of js-api and lib automatically" + echo "-v or -version the new version of the libraries, can also be alpha|beta|latest" echo "-gnu for gnu" } -skip_js() { - echo "====== Skip JS-API change version $1 =====" - JS_API=false -} - -last_alpha_mode() { - echo "====== Auto find last ALPHA version =====" - VERSION=$(npm view @alfresco/adf-core@alpha version) - - echo "====== version lib ${VERSION} =====" - - DIFFERENT_JS_API=true - VERSION_JS_API=$(npm view alfresco-js-api@alpha version) - - echo "====== version js-api ${DIFFERENT_JS_API} =====" -} - -last_beta_mode() { - echo "====== Auto find last BETA version =====" - VERSION=$(npm view @alfresco/adf-core@beta version) - - echo "====== version lib ${VERSION} =====" - - DIFFERENT_JS_API=true - VERSION_JS_API=$(npm view alfresco-js-api@beta version) - - echo "====== version js-api ${DIFFERENT_JS_API} =====" -} - -gnu_mode() { - echo "====== GNU MODE =====" +set_gnu_mode() { GNU=true } -version_change() { - echo "====== New version $1 =====" +set_version() { VERSION=$1 } -version_js_change() { - echo "====== Alfresco JS-API version $1 =====" - VERSION_JS_API=$1 - DIFFERENT_JS_API=true -} - -update_component_dependency_version(){ +update(){ for (( j=0; j<${libslength}; j++ )); do - echo "====== UPDATE ${prefix}${libs[$j]} to ${VERSION}======" - EXACT_VERSION="${prefix}${libs[$j]}@${VERSION}" - npm install -E ${EXACT_VERSION} + EXACT_VERSION="${libs[$j]}@${VERSION}" + echo "====== ${EXACT_VERSION} ======" + npm i -E ${EXACT_VERSION} done } -update_component_js_version(){ - echo "====== UPDATE alfresco-js-api to ${1} ======" - PACKAGETOCHANGE="alfresco-js-api" - EXACT_VERSION="${PACKAGETOCHANGE}@${1}" - npm install -E ${EXACT_VERSION} -} - while [[ $1 == -* ]]; do case "$1" in -h|--help|-\?) show_help; exit 0;; - -v|version) version_change $2; shift 2;; - -sj|sjsapi) skip_js; shift;; - -vj|versionjsapi) version_js_change $2; shift 2;; - -gnu) gnu_mode; shift;; - -alpha) last_alpha_mode; shift;; - -beta) last_beta_mode; shift;; + -v|version) set_version $2; shift 2;; + -gnu) set_gnu_mode; shift;; -*) shift;; esac done @@ -111,25 +52,11 @@ fi if [[ "${VERSION}" == "" ]] then - echo "Version number required" + echo "Error: version number is required" exit 1 fi -projectslength=${#projects[@]} libslength=${#libs[@]} -if $EXEC_COMPONENT == true; then - echo "====== UPDATE ======" - - update_component_dependency_version - - if $JS_API == true; then - - if $DIFFERENT_JS_API == true; then - update_component_js_version ${VERSION_JS_API} - else - update_component_js_version ${VERSION} - fi - - fi -fi +echo "====== Updating dependencies ======" +update diff --git a/src/app.config.json b/src/app.config.json index 0b6d1f9335..e090e2371b 100644 --- a/src/app.config.json +++ b/src/app.config.json @@ -1,25 +1,25 @@ { "ecmHost": "{protocol}//{hostname}{:port}", - "baseShareUrl": null, + "aosHost": "{protocol}//{hostname}{:port}/alfresco/aos", + "baseShareUrl": "{protocol}//{hostname}{:port}/#/preview/s", "providers": "ECM", "authType": "BASIC", "oauth2": { - "host": "http://localhost:30081/auth/realms/myrealm", + "host": "http://localhost:4200/auth/realms/alfresco", "clientId": "alfresco", "scope": "openid", "secret": "", "implicitFlow": true, "silentLogin": true, - "redirectSilentIframeUri": "/assets/silent-refresh.html", + "redirectSilentIframeUri": "./assets/silent-refresh.html", "redirectUri": "/", "redirectUriLogout": "/logout" }, "application": { "name": "Alfresco Content Application", "logo": "assets/images/alfresco-logo-flower.svg", - "copyright": "© 2017 - 2018 Alfresco Software, Inc. All rights reserved." + "copyright": "© 2017 - 2019 Alfresco Software, Inc. All rights reserved." }, - "experimental": {}, "headerColor": "#2196F3", "languagePicker": false, "pagination": { @@ -43,7 +43,7 @@ "languages": [ { "key": "de", - "label": "German" + "label": "Deutsch" }, { "key": "en", @@ -51,39 +51,39 @@ }, { "key": "es", - "label": "Spanish" + "label": "Español" }, { "key": "fr", - "label": "French" + "label": "Français" }, { "key": "it", - "label": "Italian" + "label": "Italiano" }, { "key": "ja", - "label": "Japanese" + "label": "日本語" }, { "key": "nb", - "label": "Norwegian" + "label": "Bokmål" }, { "key": "nl", - "label": "Dutch" + "label": "Nederlands" }, { "key": "pt-BR", - "label": "Brazilian Portuguese" + "label": "Português (Brasil)" }, { "key": "ru", - "label": "Russian" + "label": "Русский" }, { "key": "zh-CN", - "label": "Simplified Chinese" + "label": "中文简体" } ], "content-metadata": { @@ -119,10 +119,6 @@ "cm:name", "cm:title", "cm:description", - "ia:whatEvent", - "ia:descriptionEvent", - "lnk:title", - "lnk:description", "TEXT", "TAG" ], @@ -134,7 +130,7 @@ "label": "SEARCH.SORT.RELEVANCE", "type": "FIELD", "field": "score", - "ascending": true + "ascending": false }, { "key": "name", @@ -195,6 +191,7 @@ } ] }, + "aca:triggeredOnChange": false, "filterQueries": [ { "query": "+TYPE:'cm:folder' OR +TYPE:'cm:content'" }, { @@ -238,6 +235,8 @@ }, "facetQueries": { "label": "SEARCH.CATEGORIES.MODIFIED_DATE", + "expanded": true, + "mincount": 0, "queries": [ { "label": "Today", "query": "cm:modified:[TODAY to TODAY]" }, { @@ -249,7 +248,7 @@ "query": "cm:modified:[NOW/DAY-1MONTH TO NOW/DAY+1DAY]" }, { - "label": "In last 6 months", + "label": "In the last 6 months", "query": "cm:modified:[NOW/DAY-6MONTHS TO NOW/DAY+1DAY]" }, { diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index a99d54b51c..368016e760 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -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 @@ -24,20 +24,31 @@ */ import { AppComponent } from './app.component'; +import { SetInitialStateAction } from './store/actions'; describe('AppComponent', () => { - let component; - const storeMock = { + let component: AppComponent; + + const storeMock: any = { dispatch: jasmine.createSpy('dispatch') }; + const configMock: any = { + get: (key: string) => { + if (key === 'baseShareUrl') { + return 'http://localhost:4200/#/preview/s'; + } + return null; + } + }; + beforeAll(() => { component = new AppComponent( null, null, null, storeMock, - null, + configMock, null, null, null, @@ -47,48 +58,59 @@ describe('AppComponent', () => { ); }); - describe('onFileUploadedError', () => { - afterEach(() => { - storeMock.dispatch['calls'].reset(); + beforeEach(() => { + storeMock.dispatch = jasmine.createSpy('dispatch'); + }); + + it('should setup baseShareUrl as per config', done => { + storeMock.dispatch.and.callFake((action: SetInitialStateAction) => { + expect(action.payload.sharedUrl).toBe( + 'http://localhost:4200/#/preview/s/' + ); + done(); }); + component.loadAppSettings(); + }); + + describe('onFileUploadedError', () => { it('should dispatch 403 error message', () => { - component.onFileUploadedError({ error: { status: 403 } }); + component.onFileUploadedError({ error: { status: 403 } }); expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe( 'APP.MESSAGES.UPLOAD.ERROR.403' ); }); it('should dispatch 404 error message', () => { - component.onFileUploadedError({ error: { status: 404 } }); + component.onFileUploadedError({ error: { status: 404 } }); expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe( 'APP.MESSAGES.UPLOAD.ERROR.404' ); }); it('should dispatch 409 error message', () => { - component.onFileUploadedError({ error: { status: 409 } }); + component.onFileUploadedError({ error: { status: 409 } }); expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe( 'APP.MESSAGES.UPLOAD.ERROR.CONFLICT' ); }); it('should dispatch 500 error message', () => { - component.onFileUploadedError({ error: { status: 500 } }); + component.onFileUploadedError({ error: { status: 500 } }); expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe( 'APP.MESSAGES.UPLOAD.ERROR.500' ); }); it('should dispatch 504 error message', () => { - component.onFileUploadedError({ error: { status: 504 } }); + component.onFileUploadedError({ error: { status: 504 } }); expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe( 'APP.MESSAGES.UPLOAD.ERROR.504' ); }); it('should dispatch generic error message', () => { - component.onFileUploadedError({ error: { status: 999 } }); + component.onFileUploadedError({ error: { status: 999 } }); expect(storeMock.dispatch['calls'].argsFor(0)[0].payload).toBe( 'APP.MESSAGES.UPLOAD.ERROR.GENERIC' ); diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 85c3cdb474..ad62ac19fd 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -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 @@ -40,7 +40,7 @@ import { SetCurrentUrlAction, SetInitialStateAction, CloseModalDialogsAction, - SetRepositoryStatusAction, + SetRepositoryInfoAction, SetUserProfileAction } from './store/actions'; import { @@ -50,7 +50,7 @@ import { } from './store/states/app.state'; import { filter, takeUntil } from 'rxjs/operators'; import { ContentApiService } from './services/content-api.service'; -import { DiscoveryEntry } from 'alfresco-js-api'; +import { DiscoveryEntry } from '@alfresco/js-api'; import { AppService } from './services/app.service'; import { Subject } from 'rxjs'; @@ -81,8 +81,14 @@ export class AppComponent implements OnInit, OnDestroy { if (error.status === 401) { if (!this.authenticationService.isLoggedIn()) { this.store.dispatch(new CloseModalDialogsAction()); + + let redirectUrl = this.route.snapshot.queryParams['redirectUrl']; + if (!redirectUrl) { + redirectUrl = this.router.url; + } + this.router.navigate(['/login'], { - queryParams: { returnUrl: 'personal-files' } + queryParams: { redirectUrl: redirectUrl } }); } } @@ -136,7 +142,7 @@ export class AppComponent implements OnInit, OnDestroy { .getRepositoryInformation() .subscribe((response: DiscoveryEntry) => { this.store.dispatch( - new SetRepositoryStatusAction(response.entry.repository.status) + new SetRepositoryInfoAction(response.entry.repository) ); }); } @@ -147,10 +153,11 @@ export class AppComponent implements OnInit, OnDestroy { }); } - private loadAppSettings() { - const baseShareUrl = - this.config.get('baseShareUrl') || - this.config.get('ecmHost'); + loadAppSettings() { + let baseShareUrl = this.config.get('baseShareUrl'); + if (!baseShareUrl.endsWith('/')) { + baseShareUrl += '/'; + } const state: AppState = { ...INITIAL_APP_STATE, @@ -158,7 +165,7 @@ export class AppComponent implements OnInit, OnDestroy { appName: this.config.get('application.name'), headerColor: this.config.get('headerColor'), logoPath: this.config.get('application.logo'), - sharedUrl: `${baseShareUrl}/#/preview/s/` + sharedUrl: baseShareUrl }; this.store.dispatch(new SetInitialStateAction(state)); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 89fdb98643..639f0ccc74 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -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 @@ -38,6 +38,7 @@ import { DebugAppConfigService } from '@alfresco/adf-core'; import { + LibraryDialogComponent, ContentModule, CustomResourcesService } from '@alfresco/adf-content-services'; @@ -48,8 +49,8 @@ import { APP_ROUTES } from './app.routes'; import { FilesComponent } from './components/files/files.component'; import { LibrariesComponent } from './components/libraries/libraries.component'; import { FavoriteLibrariesComponent } from './components/favorite-libraries/favorite-libraries.component'; +import { NodeVersionUploadDialogComponent } from './dialogs/node-version-upload/node-version-upload.dialog'; import { NodeVersionsDialogComponent } from './dialogs/node-versions/node-versions.dialog'; -import { LibraryDialogComponent } from './dialogs/library/library.dialog'; import { AppStoreModule } from './store/app-store.module'; import { MaterialModule } from './material.module'; @@ -69,9 +70,11 @@ import { AppCommonModule } from './components/common/common.module'; import { AppLayoutModule } from './components/layout/layout.module'; import { AppCurrentUserModule } from './components/current-user/current-user.module'; import { AppSearchInputModule } from './components/search/search-input.module'; +import { DocumentListCustomComponentsModule } from './components/dl-custom-components/document-list-custom-components.module'; import { AppSearchResultsModule } from './components/search/search-results.module'; import { AppLoginModule } from './components/login/login.module'; import { AppHeaderModule } from './components/header/header.module'; +import { AppNodeVersionModule } from './components/node-version/node-version.module'; import { environment } from '../environments/environment'; import { AppDataService } from './services/data.service'; @@ -103,18 +106,20 @@ import { AppDataService } from './services/data.service'; AppSharedModule, AppSidenavModule, AppCreateMenuModule, + DocumentListCustomComponentsModule, AppPermissionsModule, AppSearchInputModule, AppSearchResultsModule, - AppHeaderModule + AppHeaderModule, + AppNodeVersionModule ], declarations: [ AppComponent, FilesComponent, LibrariesComponent, FavoriteLibrariesComponent, - NodeVersionsDialogComponent, - LibraryDialogComponent + NodeVersionUploadDialogComponent, + NodeVersionsDialogComponent ], providers: [ { provide: RouteReuseStrategy, useClass: AppRouteReuseStrategy }, @@ -129,7 +134,11 @@ import { AppDataService } from './services/data.service'; } } ], - entryComponents: [LibraryDialogComponent, NodeVersionsDialogComponent], + entryComponents: [ + NodeVersionsDialogComponent, + NodeVersionUploadDialogComponent, + LibraryDialogComponent + ], bootstrap: [AppComponent] }) export class AppModule {} diff --git a/src/app/app.routes.strategy.spec.ts b/src/app/app.routes.strategy.spec.ts new file mode 100644 index 0000000000..674e430a50 --- /dev/null +++ b/src/app/app.routes.strategy.spec.ts @@ -0,0 +1,88 @@ +/*! + * @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 . + */ + +import { AppRouteReuseStrategy } from './app.routes.strategy'; +import { TestBed } from '@angular/core/testing'; +import { AppTestingModule } from './testing/app-testing.module'; + +describe('AppRouteReuseStrategy', () => { + let appRouteReuse: AppRouteReuseStrategy; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [AppTestingModule], + providers: [AppRouteReuseStrategy] + }); + + appRouteReuse = TestBed.get(AppRouteReuseStrategy); + }); + + it('should allow detach if route is configured to be reused', () => { + const route = { + routeConfig: { + data: { + reuse: true + }, + path: 'tested-path' + } + }; + expect(appRouteReuse.shouldDetach(route)).toBe(true); + }); + + it('should store on routeCache', () => { + const route = { + url: [], + routeConfig: { + data: { + reuse: true + }, + path: 'tested-path', + component: {} + }, + firstChild: null, + children: [] + }; + appRouteReuse.store(route, { route: {} }); + expect(appRouteReuse.shouldAttach(route)).toBe(true); + }); + + it('should clear routeCache on resetCache', () => { + const route = { + url: [], + routeConfig: { + data: { + reuse: true + }, + path: 'tested-path', + component: {} + }, + firstChild: null, + children: [] + }; + appRouteReuse.store(route, { route: {} }); + appRouteReuse.resetCache(); + expect(appRouteReuse.shouldAttach(route)).toBe(false); + }); +}); diff --git a/src/app/app.routes.strategy.ts b/src/app/app.routes.strategy.ts index ff5c8e58d1..ee134a6cdb 100644 --- a/src/app/app.routes.strategy.ts +++ b/src/app/app.routes.strategy.ts @@ -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,6 +28,7 @@ import { DetachedRouteHandle, ActivatedRouteSnapshot } from '@angular/router'; +import { ComponentRef } from '@angular/core'; interface RouteData { reuse: boolean; @@ -41,6 +42,23 @@ interface RouteInfo { export class AppRouteReuseStrategy implements RouteReuseStrategy { private routeCache = new Map(); + resetCache() { + this.routeCache.forEach(value => { + this.deactivateComponent(value.handle); + }); + this.routeCache.clear(); + } + + private deactivateComponent(handle: DetachedRouteHandle): void { + if (!handle) { + return; + } + const componentRef: ComponentRef = handle['componentRef']; + if (componentRef) { + componentRef.destroy(); + } + } + shouldReuseRoute( future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index e80b7149be..9e2ca69076 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -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 diff --git a/src/app/components/about/about.component.spec.ts b/src/app/components/about/about.component.spec.ts index 63b3dc7c01..41f8c5b1cd 100644 --- a/src/app/components/about/about.component.spec.ts +++ b/src/app/components/about/about.component.spec.ts @@ -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 diff --git a/src/app/components/about/about.component.ts b/src/app/components/about/about.component.ts index 63075faf7a..c6e1720991 100644 --- a/src/app/components/about/about.component.ts +++ b/src/app/components/about/about.component.ts @@ -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 @@ -25,7 +25,7 @@ import { ExtensionRef } from '@alfresco/adf-extensions'; import { Component, OnInit, ViewEncapsulation } from '@angular/core'; -import { RepositoryInfo } from 'alfresco-js-api'; +import { RepositoryInfo } from '@alfresco/js-api'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { AppExtensionService } from '../../extensions/extension.service'; diff --git a/src/app/components/about/about.module.ts b/src/app/components/about/about.module.ts index 157b9174aa..aa2fd1beac 100644 --- a/src/app/components/about/about.module.ts +++ b/src/app/components/about/about.module.ts @@ -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 diff --git a/src/app/components/about/extension-list/extension-list.component.ts b/src/app/components/about/extension-list/extension-list.component.ts index 05977060d7..b3afc04889 100644 --- a/src/app/components/about/extension-list/extension-list.component.ts +++ b/src/app/components/about/extension-list/extension-list.component.ts @@ -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 diff --git a/src/app/components/about/license-list/license-list.component.ts b/src/app/components/about/license-list/license-list.component.ts index 6a2157d60c..cf5482f031 100644 --- a/src/app/components/about/license-list/license-list.component.ts +++ b/src/app/components/about/license-list/license-list.component.ts @@ -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 diff --git a/src/app/components/about/module-list/module-list.component.ts b/src/app/components/about/module-list/module-list.component.ts index f4d5aa7cf3..7b14da89bc 100644 --- a/src/app/components/about/module-list/module-list.component.ts +++ b/src/app/components/about/module-list/module-list.component.ts @@ -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 @@ -29,7 +29,7 @@ import { ChangeDetectionStrategy, Input } from '@angular/core'; -import { ModuleInfo } from 'alfresco-js-api'; +import { ModuleInfo } from '@alfresco/js-api'; @Component({ selector: 'app-module-list', diff --git a/src/app/components/about/package-list/package-list.component.ts b/src/app/components/about/package-list/package-list.component.ts index 606df66f99..206e48969c 100644 --- a/src/app/components/about/package-list/package-list.component.ts +++ b/src/app/components/about/package-list/package-list.component.ts @@ -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 diff --git a/src/app/components/about/status-list/status-list.component.ts b/src/app/components/about/status-list/status-list.component.ts index 0223b3d681..d8bb86c4af 100644 --- a/src/app/components/about/status-list/status-list.component.ts +++ b/src/app/components/about/status-list/status-list.component.ts @@ -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 diff --git a/src/app/components/common/common.module.ts b/src/app/components/common/common.module.ts index 9dd9d1429d..c1a0973e76 100644 --- a/src/app/components/common/common.module.ts +++ b/src/app/components/common/common.module.ts @@ -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,46 +28,18 @@ import { CommonModule } from '@angular/common'; import { GenericErrorComponent } from './generic-error/generic-error.component'; import { CoreModule } from '@alfresco/adf-core'; import { LocationLinkComponent } from './location-link/location-link.component'; -import { NameColumnComponent } from './name-column/name-column.component'; -import { LibraryNameColumnComponent } from './library-name-column/library-name-column.component'; -import { LibraryStatusColumnComponent } from './library-status-column/library-status-column.component'; -import { LibraryRoleColumnComponent } from './library-role-column/library-role-column.component'; -import { TrashcanNameColumnComponent } from './trashcan-name-column/trashcan-name-column.component'; -import { DynamicColumnComponent } from './dynamic-column/dynamic-column.component'; -import { IconComponent } from './icon/icon.component'; import { MatIconModule } from '@angular/material'; +import { ExtensionsModule } from '@alfresco/adf-extensions'; @NgModule({ - imports: [CommonModule, CoreModule.forChild(), MatIconModule], - declarations: [ - GenericErrorComponent, - LocationLinkComponent, - NameColumnComponent, - LibraryNameColumnComponent, - LibraryStatusColumnComponent, - LibraryRoleColumnComponent, - TrashcanNameColumnComponent, - DynamicColumnComponent, - IconComponent + imports: [ + CommonModule, + CoreModule.forChild(), + MatIconModule, + ExtensionsModule ], - exports: [ - GenericErrorComponent, - LocationLinkComponent, - NameColumnComponent, - LibraryNameColumnComponent, - LibraryStatusColumnComponent, - LibraryRoleColumnComponent, - TrashcanNameColumnComponent, - DynamicColumnComponent, - IconComponent - ], - entryComponents: [ - LocationLinkComponent, - NameColumnComponent, - LibraryNameColumnComponent, - LibraryStatusColumnComponent, - LibraryRoleColumnComponent, - TrashcanNameColumnComponent - ] + declarations: [GenericErrorComponent, LocationLinkComponent], + exports: [ExtensionsModule, GenericErrorComponent, LocationLinkComponent], + entryComponents: [LocationLinkComponent] }) export class AppCommonModule {} diff --git a/src/app/components/common/dynamic-column/dynamic-column.component.ts b/src/app/components/common/dynamic-column/dynamic-column.component.ts deleted file mode 100644 index 4ad17fae52..0000000000 --- a/src/app/components/common/dynamic-column/dynamic-column.component.ts +++ /dev/null @@ -1,108 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { - Component, - Input, - OnInit, - OnDestroy, - ViewChild, - ViewContainerRef, - ComponentRef, - ComponentFactoryResolver, - OnChanges, - SimpleChanges, - ViewEncapsulation, - ChangeDetectionStrategy -} from '@angular/core'; -import { ExtensionService } from '@alfresco/adf-extensions'; - -@Component({ - selector: 'app-dynamic-column', - template: ` - - `, - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, - host: { class: 'app-dynamic-column' }, - styles: [ - ` - .app-dynamic-column { - display: flex; - align-items: center; - } - ` - ] -}) -export class DynamicColumnComponent implements OnInit, OnChanges, OnDestroy { - @ViewChild('content', { read: ViewContainerRef }) - content: ViewContainerRef; - - @Input() - id: string; - - @Input() - context: any; - - private componentRef: ComponentRef; - - constructor( - private extensions: ExtensionService, - private componentFactoryResolver: ComponentFactoryResolver - ) {} - - ngOnInit() { - const componentType = this.extensions.getComponentById(this.id); - if (componentType) { - const factory = this.componentFactoryResolver.resolveComponentFactory( - componentType - ); - if (factory) { - this.content.clear(); - this.componentRef = this.content.createComponent(factory, 0); - this.updateInstance(); - } - } - } - - ngOnChanges(changes: SimpleChanges) { - if (changes.node) { - this.updateInstance(); - } - } - - ngOnDestroy() { - if (this.componentRef) { - this.componentRef.destroy(); - this.componentRef = null; - } - } - - private updateInstance() { - if (this.componentRef && this.componentRef.instance) { - this.componentRef.instance.context = this.context; - } - } -} diff --git a/src/app/components/common/generic-error/generic-error.component.html b/src/app/components/common/generic-error/generic-error.component.html index ac7157b634..8b0419bc1b 100644 --- a/src/app/components/common/generic-error/generic-error.component.html +++ b/src/app/components/common/generic-error/generic-error.component.html @@ -1,4 +1,4 @@ ic_error

- {{ 'APP.MESSAGES.ERRORS.MISSING_CONTENT' | translate }} + {{ 'APP.MESSAGES.ERRORS.MISSING_CONTENT' | translate }}

diff --git a/src/app/components/common/generic-error/generic-error.component.spec.ts b/src/app/components/common/generic-error/generic-error.component.spec.ts index ddd53402fe..99542683f1 100644 --- a/src/app/components/common/generic-error/generic-error.component.spec.ts +++ b/src/app/components/common/generic-error/generic-error.component.spec.ts @@ -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 diff --git a/src/app/components/common/generic-error/generic-error.component.ts b/src/app/components/common/generic-error/generic-error.component.ts index c881d1f774..755cc3df96 100644 --- a/src/app/components/common/generic-error/generic-error.component.ts +++ b/src/app/components/common/generic-error/generic-error.component.ts @@ -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 diff --git a/src/app/components/common/icon/icon.component.html b/src/app/components/common/icon/icon.component.html deleted file mode 100644 index ba5b060d27..0000000000 --- a/src/app/components/common/icon/icon.component.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - {{ value }} - diff --git a/src/app/components/common/icon/icon.component.scss b/src/app/components/common/icon/icon.component.scss deleted file mode 100644 index ab73482199..0000000000 --- a/src/app/components/common/icon/icon.component.scss +++ /dev/null @@ -1,4 +0,0 @@ -.adf-icon { - display: inline-flex; - vertical-align: middle; -} diff --git a/src/app/components/common/library-name-column/library-name-column.component.spec.ts b/src/app/components/common/library-name-column/library-name-column.component.spec.ts deleted file mode 100644 index 47ddc872f6..0000000000 --- a/src/app/components/common/library-name-column/library-name-column.component.spec.ts +++ /dev/null @@ -1,102 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { LibraryNameColumnComponent } from './library-name-column.component'; -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { AppTestingModule } from '../../../testing/app-testing.module'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; - -describe('LibraryNameColumnComponent', () => { - let fixture: ComponentFixture; - let component: LibraryNameColumnComponent; - let node; - - beforeEach(() => { - node = { - id: 'nodeId', - path: { - elements: [] - } - }; - }); - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [AppTestingModule], - declarations: [LibraryNameColumnComponent], - schemas: [NO_ERRORS_SCHEMA] - }); - - fixture = TestBed.createComponent(LibraryNameColumnComponent); - component = fixture.componentInstance; - }); - - describe('makeLibraryTooltip()', () => { - it('maps tooltip to description', () => { - node.description = 'description'; - const tooltip = component.makeLibraryTooltip(node); - - expect(tooltip).toBe(node.description); - }); - - it('maps tooltip to description', () => { - node.title = 'title'; - const tooltip = component.makeLibraryTooltip(node); - - expect(tooltip).toBe(node.title); - }); - - it('sets tooltip to empty string', () => { - const tooltip = component.makeLibraryTooltip(node); - - expect(tooltip).toBe(''); - }); - }); - - describe('makeLibraryTitle()', () => { - it('sets title with id when duplicate nodes title exists in list', () => { - node.title = 'title'; - - const rows = [ - { node: { entry: { id: 'some-id', title: 'title' } } } - ]; - - const title = component.makeLibraryTitle(node, rows); - expect(title).toContain('nodeId'); - }); - - it('sets title when no duplicate nodes title exists in list', () => { - node.title = 'title'; - - const rows = [ - { node: { entry: { id: 'some-id', title: 'title-some-id' } } } - ]; - - const title = component.makeLibraryTitle(node, rows); - - expect(title).toBe('title'); - }); - }); -}); diff --git a/src/app/components/common/library-name-column/library-name-column.component.ts b/src/app/components/common/library-name-column/library-name-column.component.ts deleted file mode 100644 index 8ebf3d3e45..0000000000 --- a/src/app/components/common/library-name-column/library-name-column.component.ts +++ /dev/null @@ -1,98 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { - Component, - ChangeDetectionStrategy, - ViewEncapsulation, - OnInit, - Input, - ElementRef -} from '@angular/core'; -import { MinimalNodeEntity } from 'alfresco-js-api'; -import { ShareDataRow } from '@alfresco/adf-content-services'; - -@Component({ - selector: 'app-library-name-column', - template: ` - - {{ displayText }} - - `, - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell dl-link app-library-name-column' } -}) -export class LibraryNameColumnComponent implements OnInit { - @Input() - context: any; - - displayTooltip: string; - displayText: string; - node: MinimalNodeEntity; - - constructor(private element: ElementRef) {} - - ngOnInit() { - this.node = this.context.row.node; - const rows: Array = this.context.data.rows || []; - if (this.node && this.node.entry) { - this.displayText = this.makeLibraryTitle(this.node.entry, rows); - this.displayTooltip = this.makeLibraryTooltip(this.node.entry); - } - } - - onClick() { - this.element.nativeElement.dispatchEvent( - new CustomEvent('name-click', { - bubbles: true, - detail: { - node: this.node - } - }) - ); - } - - makeLibraryTooltip(library: any): string { - const { description, title } = library; - - return description || title || ''; - } - - makeLibraryTitle(library: any, rows: Array): string { - const entries = rows.map((r: ShareDataRow) => r.node.entry); - const { title, id } = library; - - let isDuplicate = false; - - if (entries) { - isDuplicate = entries.some((entry: any) => { - return entry.id !== id && entry.title === title; - }); - } - - return isDuplicate ? `${title} (${id})` : `${title}`; - } -} diff --git a/src/app/components/common/library-role-column/library-role-column.component.spec.ts b/src/app/components/common/library-role-column/library-role-column.component.spec.ts deleted file mode 100644 index 5219430d05..0000000000 --- a/src/app/components/common/library-role-column/library-role-column.component.spec.ts +++ /dev/null @@ -1,83 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { LibraryRoleColumnComponent } from './library-role-column.component'; -import { TestBed, ComponentFixture } from '@angular/core/testing'; -import { AppTestingModule } from '../../../testing/app-testing.module'; -import { NO_ERRORS_SCHEMA } from '@angular/core'; - -describe('LibraryNameColumnComponent', () => { - let fixture: ComponentFixture; - let component: LibraryRoleColumnComponent; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [AppTestingModule], - declarations: [LibraryRoleColumnComponent], - schemas: [NO_ERRORS_SCHEMA] - }); - - fixture = TestBed.createComponent(LibraryRoleColumnComponent); - component = fixture.componentInstance; - }); - - it('should render Manager', () => { - component.context = { row: { node: { entry: { role: 'SiteManager' } } } }; - fixture.detectChanges(); - expect(component.displayText).toBe('APP.SITES_ROLE.MANAGER'); - }); - - it('should render Collaborator', () => { - component.context = { - row: { node: { entry: { role: 'SiteCollaborator' } } } - }; - fixture.detectChanges(); - expect(component.displayText).toBe('APP.SITES_ROLE.COLLABORATOR'); - }); - - it('should render Contributor', () => { - component.context = { - row: { node: { entry: { role: 'SiteContributor' } } } - }; - fixture.detectChanges(); - expect(component.displayText).toBe('APP.SITES_ROLE.CONTRIBUTOR'); - }); - - it('should render Consumer', () => { - component.context = { - row: { node: { entry: { role: 'SiteConsumer' } } } - }; - fixture.detectChanges(); - expect(component.displayText).toBe('APP.SITES_ROLE.CONSUMER'); - }); - - it('should not render text for unknown', () => { - component.context = { - row: { node: { entry: { role: 'ROLE' } } } - }; - fixture.detectChanges(); - expect(component.displayText).toBe(''); - }); -}); diff --git a/src/app/components/common/library-role-column/library-role-column.component.ts b/src/app/components/common/library-role-column/library-role-column.component.ts deleted file mode 100644 index 194b2b12ec..0000000000 --- a/src/app/components/common/library-role-column/library-role-column.component.ts +++ /dev/null @@ -1,65 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { Component, OnInit, Input } from '@angular/core'; - -@Component({ - selector: 'app-library-role-column', - template: ` - - {{ displayText | translate }} - - ` -}) -export class LibraryRoleColumnComponent implements OnInit { - @Input() - context: any; - - displayText: string; - - ngOnInit() { - const node = this.context.row.node; - if (node && node.entry) { - const role: string = node.entry.role; - switch (role) { - case 'SiteManager': - this.displayText = 'APP.SITES_ROLE.MANAGER'; - break; - case 'SiteCollaborator': - this.displayText = 'APP.SITES_ROLE.COLLABORATOR'; - break; - case 'SiteContributor': - this.displayText = 'APP.SITES_ROLE.CONTRIBUTOR'; - break; - case 'SiteConsumer': - this.displayText = 'APP.SITES_ROLE.CONSUMER'; - break; - default: - this.displayText = ''; - break; - } - } - } -} diff --git a/src/app/components/common/library-status-column/library-status-column.component.spec.ts b/src/app/components/common/library-status-column/library-status-column.component.spec.ts deleted file mode 100644 index 5aad9e139f..0000000000 --- a/src/app/components/common/library-status-column/library-status-column.component.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { LibraryStatusColumnComponent } from './library-status-column.component'; - -describe('LibraryStatusColumnComponent', () => { - it('should be defined', () => { - expect(LibraryStatusColumnComponent).toBeDefined(); - }); -}); diff --git a/src/app/components/common/library-status-column/library-status-column.component.ts b/src/app/components/common/library-status-column/library-status-column.component.ts deleted file mode 100644 index 081f35e0f8..0000000000 --- a/src/app/components/common/library-status-column/library-status-column.component.ts +++ /dev/null @@ -1,63 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { Component, Input, OnInit } from '@angular/core'; - -@Component({ - selector: 'app-library-status-column', - template: ` - - {{ displayText | translate }} - - ` -}) -export class LibraryStatusColumnComponent implements OnInit { - @Input() - context: any; - - displayText: string; - - ngOnInit() { - const node = this.context.row.node; - if (node && node.entry) { - const visibility: string = node.entry.visibility; - - switch (visibility.toUpperCase()) { - case 'PUBLIC': - this.displayText = 'APP.SITES_VISIBILITY.PUBLIC'; - break; - case 'PRIVATE': - this.displayText = 'APP.SITES_VISIBILITY.PRIVATE'; - break; - case 'MODERATED': - this.displayText = 'APP.SITES_VISIBILITY.MODERATED'; - break; - default: - this.displayText = 'UNKNOWN'; - break; - } - } - } -} diff --git a/src/app/components/common/location-link/location-link.component.spec.ts b/src/app/components/common/location-link/location-link.component.spec.ts index f1f033edc8..c70da479ad 100644 --- a/src/app/components/common/location-link/location-link.component.spec.ts +++ b/src/app/components/common/location-link/location-link.component.spec.ts @@ -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 diff --git a/src/app/components/common/location-link/location-link.component.ts b/src/app/components/common/location-link/location-link.component.ts index 018e21e324..6a0280d99b 100644 --- a/src/app/components/common/location-link/location-link.component.ts +++ b/src/app/components/common/location-link/location-link.component.ts @@ -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 @@ -31,7 +31,7 @@ import { ViewEncapsulation, HostListener } from '@angular/core'; -import { PathInfo, MinimalNodeEntity } from 'alfresco-js-api'; +import { PathInfo, MinimalNodeEntity } from '@alfresco/js-api'; import { Observable, BehaviorSubject, of } from 'rxjs'; import { Store } from '@ngrx/store'; diff --git a/src/app/components/common/name-column/name-column.component.ts b/src/app/components/common/name-column/name-column.component.ts deleted file mode 100644 index 9f328689ec..0000000000 --- a/src/app/components/common/name-column/name-column.component.ts +++ /dev/null @@ -1,73 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { - Component, - Input, - OnInit, - ChangeDetectionStrategy, - ViewEncapsulation, - ElementRef -} from '@angular/core'; -import { MinimalNodeEntity } from 'alfresco-js-api'; - -@Component({ - selector: 'app-name-column', - template: ` - - {{ displayText }} - - `, - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell dl-link app-name-column' } -}) -export class NameColumnComponent implements OnInit { - @Input() - context: any; - - displayText: string; - node: MinimalNodeEntity; - - constructor(private element: ElementRef) {} - - ngOnInit() { - this.node = this.context.row.node; - if (this.node && this.node.entry) { - this.displayText = this.node.entry.name || this.node.entry.id; - } - } - - onClick() { - this.element.nativeElement.dispatchEvent( - new CustomEvent('name-click', { - bubbles: true, - detail: { - node: this.node - } - }) - ); - } -} diff --git a/src/app/components/common/trashcan-name-column/trashcan-name-column.component.spec.ts b/src/app/components/common/trashcan-name-column/trashcan-name-column.component.spec.ts deleted file mode 100644 index cfc7129c52..0000000000 --- a/src/app/components/common/trashcan-name-column/trashcan-name-column.component.spec.ts +++ /dev/null @@ -1,114 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { TrashcanNameColumnComponent } from './trashcan-name-column.component'; - -describe('TrashcanNameColumnComponent', () => { - let component; - - beforeEach(() => { - component = new TrashcanNameColumnComponent(); - }); - - it('should set displayText for content files', () => { - const context = { - data: { rows: [] }, - row: { - node: { - entry: { - name: 'contentName', - nodeType: 'content' - } - } - } - }; - - component.context = context; - component.ngOnInit(); - - expect(component.displayText).toBe('contentName'); - }); - - it('should set displayText for library', () => { - const context = { - data: { - rows: [] - }, - row: { - node: { - entry: { - nodeType: 'st:site', - properties: { - 'cm:title': 'libraryTitle' - } - } - } - } - }; - - component.context = context; - component.ngOnInit(); - - expect(component.displayText).toBe('libraryTitle'); - }); - - it('should set custom displayText for libraries with same name', () => { - const context = { - data: { - rows: [ - { - node: { - entry: { - id: 'id1', - name: 'name1', - nodeType: 'st:site', - properties: { - 'cm:title': 'bogus' - } - } - } - } - ] - }, - row: { - node: { - entry: { - id: 'id2', - name: 'name1', - nodeType: 'st:site', - properties: { - 'cm:title': 'bogus' - } - } - } - } - }; - - component.context = context; - component.ngOnInit(); - - expect(component.displayText).toBe('bogus (name1)'); - }); -}); diff --git a/src/app/components/common/trashcan-name-column/trashcan-name-column.component.ts b/src/app/components/common/trashcan-name-column/trashcan-name-column.component.ts deleted file mode 100644 index 627c246fce..0000000000 --- a/src/app/components/common/trashcan-name-column/trashcan-name-column.component.ts +++ /dev/null @@ -1,95 +0,0 @@ -/*! - * @license - * Alfresco Example Content Application - * - * Copyright (C) 2005 - 2018 Alfresco Software Limited - * - * This file is part of the Alfresco Example Content Application. - * If the software was purchased under a paid Alfresco license, the terms of - * the paid license agreement will prevail. Otherwise, the software is - * provided under the following open source license terms: - * - * The Alfresco Example Content Application is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Alfresco Example Content Application is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - */ - -import { - Component, - ChangeDetectionStrategy, - ViewEncapsulation, - OnInit, - Input -} from '@angular/core'; -import { ShareDataRow } from '@alfresco/adf-content-services'; -import { MinimalNodeEntity } from 'alfresco-js-api'; - -@Component({ - selector: 'app-trashcan-name-column', - template: ` - - {{ displayText }} - - - {{ displayText }} - - `, - changeDetection: ChangeDetectionStrategy.OnPush, - encapsulation: ViewEncapsulation.None, - host: { class: 'adf-datatable-cell app-trashcan-name-column' } -}) -export class TrashcanNameColumnComponent implements OnInit { - @Input() - context: any; - - isLibrary = false; - displayText: string; - displayTooltip: string; - node: MinimalNodeEntity; - - ngOnInit() { - this.node = this.context.row.node; - const rows: Array = this.context.data.rows || []; - - if (this.node && this.node.entry) { - this.isLibrary = this.node.entry.nodeType === 'st:site'; - - if (this.isLibrary) { - const { properties } = this.node.entry; - - this.displayText = this.makeLibraryTitle(this.node.entry, rows); - this.displayTooltip = - properties['cm:description'] || properties['cm:title']; - } else { - this.displayText = this.node.entry.name || this.node.entry.id; - } - } - } - - makeLibraryTitle(library: any, rows: Array): string { - const entries = rows.map((r: ShareDataRow) => r.node.entry); - const { id } = library; - const title = library.properties['cm:title']; - - let isDuplicate = false; - - if (entries) { - isDuplicate = entries.some((entry: any) => { - return entry.id !== id && entry.properties['cm:title'] === title; - }); - } - - return isDuplicate - ? `${library.properties['cm:title']} (${library.name})` - : `${library.properties['cm:title']}`; - } -} diff --git a/src/app/components/context-menu/context-menu-item.component.spec.ts b/src/app/components/context-menu/context-menu-item.component.spec.ts index 581b1b9349..6d12244da5 100644 --- a/src/app/components/context-menu/context-menu-item.component.spec.ts +++ b/src/app/components/context-menu/context-menu-item.component.spec.ts @@ -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 diff --git a/src/app/components/context-menu/context-menu-item.component.ts b/src/app/components/context-menu/context-menu-item.component.ts index ac2a17f6fc..6d753c6629 100644 --- a/src/app/components/context-menu/context-menu-item.component.ts +++ b/src/app/components/context-menu/context-menu-item.component.ts @@ -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 diff --git a/src/app/components/context-menu/context-menu-outside-event.directive.spec.ts b/src/app/components/context-menu/context-menu-outside-event.directive.spec.ts index fe1f7137f4..59bb3ff1f3 100644 --- a/src/app/components/context-menu/context-menu-outside-event.directive.spec.ts +++ b/src/app/components/context-menu/context-menu-outside-event.directive.spec.ts @@ -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 diff --git a/src/app/components/context-menu/context-menu-overlay.ts b/src/app/components/context-menu/context-menu-overlay.ts index 9053444b24..2e9fc47054 100644 --- a/src/app/components/context-menu/context-menu-overlay.ts +++ b/src/app/components/context-menu/context-menu-overlay.ts @@ -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 diff --git a/src/app/components/context-menu/context-menu.component.spec.ts b/src/app/components/context-menu/context-menu.component.spec.ts index 7eb44d24fa..dab3d84a97 100644 --- a/src/app/components/context-menu/context-menu.component.spec.ts +++ b/src/app/components/context-menu/context-menu.component.spec.ts @@ -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 diff --git a/src/app/components/context-menu/context-menu.component.ts b/src/app/components/context-menu/context-menu.component.ts index 84d77fe062..fa98615ab9 100644 --- a/src/app/components/context-menu/context-menu.component.ts +++ b/src/app/components/context-menu/context-menu.component.ts @@ -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 diff --git a/src/app/components/context-menu/context-menu.directive.ts b/src/app/components/context-menu/context-menu.directive.ts index 5fb5af91cf..8c33226d3e 100644 --- a/src/app/components/context-menu/context-menu.directive.ts +++ b/src/app/components/context-menu/context-menu.directive.ts @@ -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 @@ -109,7 +109,7 @@ export class ContextActionsDirective implements OnInit, OnDestroy { } return this.findAncestor(target, 'adf-datatable-row').classList.contains( - 'is-selected' + 'adf-is-selected' ); } diff --git a/src/app/components/context-menu/context-menu.directives.spec.ts b/src/app/components/context-menu/context-menu.directives.spec.ts index 13d57e0f14..bea806d9ff 100644 --- a/src/app/components/context-menu/context-menu.directives.spec.ts +++ b/src/app/components/context-menu/context-menu.directives.spec.ts @@ -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 diff --git a/src/app/components/context-menu/context-menu.module.ts b/src/app/components/context-menu/context-menu.module.ts index ab267b9cd5..90b203d424 100644 --- a/src/app/components/context-menu/context-menu.module.ts +++ b/src/app/components/context-menu/context-menu.module.ts @@ -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 diff --git a/src/app/components/context-menu/context-menu.service.spec.ts b/src/app/components/context-menu/context-menu.service.spec.ts index b11cd02467..5ac488db65 100644 --- a/src/app/components/context-menu/context-menu.service.spec.ts +++ b/src/app/components/context-menu/context-menu.service.spec.ts @@ -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,7 +28,7 @@ import { Overlay } from '@angular/cdk/overlay'; import { Injector } from '@angular/core'; import { Store } from '@ngrx/store'; import { of } from 'rxjs'; -import { AppConfigService } from '@alfresco/adf-core'; +import { CoreModule } from '@alfresco/adf-core'; import { ContextMenuService } from './context-menu.service'; import { ContextMenuModule } from './context-menu.module'; @@ -42,12 +42,8 @@ describe('ContextMenuService', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [ContextMenuModule], - providers: [ - Overlay, - { provide: Store, useValue: { select: () => of() } }, - { provide: AppConfigService, useValue: {} } - ] + imports: [CoreModule.forRoot(), ContextMenuModule], + providers: [Overlay, { provide: Store, useValue: { select: () => of() } }] }); const injector = TestBed.get(Injector); diff --git a/src/app/components/context-menu/interfaces.ts b/src/app/components/context-menu/interfaces.ts index 51fb28324b..e28b55216f 100644 --- a/src/app/components/context-menu/interfaces.ts +++ b/src/app/components/context-menu/interfaces.ts @@ -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 diff --git a/src/app/components/create-menu/create-menu.component.html b/src/app/components/create-menu/create-menu.component.html index 411c58632d..bf21d132a9 100644 --- a/src/app/components/create-menu/create-menu.component.html +++ b/src/app/components/create-menu/create-menu.component.html @@ -3,9 +3,14 @@ data-automation-id="create-button" mat-raised-button [matMenuTriggerFor]="rootMenu" - title="{{ 'APP.NEW_MENU.TOOLTIP' | translate }}"> - {{ 'APP.NEW_MENU.LABEL' | translate }} - arrow_drop_down + title="{{ 'APP.NEW_MENU.TOOLTIP' | translate }}" + > + {{ + 'APP.NEW_MENU.LABEL' | translate + }} + arrow_drop_down @@ -17,12 +22,22 @@ data-automation-id="create-button" [matMenuTriggerFor]="rootMenu" #createMenu="matMenuTrigger" - title="{{ 'APP.NEW_MENU.TOOLTIP' | translate }}"> - queue + title="{{ 'APP.NEW_MENU.TOOLTIP' | translate }}" + > + queue - + diff --git a/src/app/components/create-menu/create-menu.component.spec.ts b/src/app/components/create-menu/create-menu.component.spec.ts index 98734a8326..0c426677c6 100644 --- a/src/app/components/create-menu/create-menu.component.spec.ts +++ b/src/app/components/create-menu/create-menu.component.spec.ts @@ -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 diff --git a/src/app/components/create-menu/create-menu.component.ts b/src/app/components/create-menu/create-menu.component.ts index a00d69215a..654df11f31 100644 --- a/src/app/components/create-menu/create-menu.component.ts +++ b/src/app/components/create-menu/create-menu.component.ts @@ -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 diff --git a/src/app/components/create-menu/create-menu.module.ts b/src/app/components/create-menu/create-menu.module.ts index f0211c9f1b..841b80c294 100644 --- a/src/app/components/create-menu/create-menu.module.ts +++ b/src/app/components/create-menu/create-menu.module.ts @@ -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 diff --git a/src/app/components/current-user/current-user.component.html b/src/app/components/current-user/current-user.component.html index 1c566f2dae..8a32ab9b5f 100644 --- a/src/app/components/current-user/current-user.component.html +++ b/src/app/components/current-user/current-user.component.html @@ -1,23 +1,26 @@
-
{{ (profile$ | async)?.userName }}
-
- {{ (profile$ | async)?.initials }} -
+
{{ (profile$ | async)?.userName }}
+
+ {{ (profile$ | async)?.initials }} +
- + + + - + diff --git a/src/app/components/current-user/current-user.component.spec.ts b/src/app/components/current-user/current-user.component.spec.ts index bcd5ea8bb4..cfb33145bb 100644 --- a/src/app/components/current-user/current-user.component.spec.ts +++ b/src/app/components/current-user/current-user.component.spec.ts @@ -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 diff --git a/src/app/components/current-user/current-user.component.ts b/src/app/components/current-user/current-user.component.ts index f250d3e5c4..64750e9ab8 100644 --- a/src/app/components/current-user/current-user.component.ts +++ b/src/app/components/current-user/current-user.component.ts @@ -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 @@ -33,6 +33,7 @@ import { import { AppStore } from '../../store/states'; import { ProfileState } from '@alfresco/adf-extensions'; import { SetSelectedNodesAction } from '../../store/actions'; +import { AppService } from '../../services/app.service'; @Component({ selector: 'aca-current-user', @@ -44,7 +45,11 @@ export class CurrentUserComponent { profile$: Observable; languagePicker$: Observable; - constructor(private store: Store) { + get showLogout(): boolean { + return !this.appService.withCredentials; + } + + constructor(private store: Store, private appService: AppService) { this.profile$ = this.store.select(selectUser); this.languagePicker$ = store.select(appLanguagePicker); } diff --git a/src/app/components/current-user/current-user.module.ts b/src/app/components/current-user/current-user.module.ts index 29c4de29a2..2fa14bc3be 100644 --- a/src/app/components/current-user/current-user.module.ts +++ b/src/app/components/current-user/current-user.module.ts @@ -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 diff --git a/src/app/components/common/icon/icon.component.ts b/src/app/components/dl-custom-components/document-list-custom-components.module.ts similarity index 59% rename from src/app/components/common/icon/icon.component.ts rename to src/app/components/dl-custom-components/document-list-custom-components.module.ts index d27b3bd733..c3c731e752 100644 --- a/src/app/components/common/icon/icon.component.ts +++ b/src/app/components/dl-custom-components/document-list-custom-components.module.ts @@ -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,36 +23,17 @@ * along with Alfresco. If not, see . */ -import { - Component, - Input, - ViewEncapsulation, - ChangeDetectionStrategy -} from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { CustomNameColumnComponent } from './name-column/name-column.component'; +import { LockByComponent } from './locked-by/locked-by.component'; +import { ContentModule } from '@alfresco/adf-content-services'; +import { MaterialModule } from '../../material.module'; -@Component({ - selector: 'adf-icon', - templateUrl: './icon.component.html', - encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, - host: { class: 'adf-icon' }, - styleUrls: ['./icon.component.scss'] +@NgModule({ + imports: [BrowserModule, ContentModule, MaterialModule], + declarations: [CustomNameColumnComponent, LockByComponent], + exports: [CustomNameColumnComponent, LockByComponent], + entryComponents: [CustomNameColumnComponent, LockByComponent] }) -export class IconComponent { - private _value = ''; - private _isCustom = false; - - get value(): string { - return this._value; - } - - @Input() - set value(value: string) { - this._value = value || 'settings'; - this._isCustom = this._value.includes(':'); - } - - get isCustom(): boolean { - return this._isCustom; - } -} +export class DocumentListCustomComponentsModule {} diff --git a/src/app/components/dl-custom-components/locked-by/locked-by.component.scss b/src/app/components/dl-custom-components/locked-by/locked-by.component.scss new file mode 100644 index 0000000000..95483bd13d --- /dev/null +++ b/src/app/components/dl-custom-components/locked-by/locked-by.component.scss @@ -0,0 +1,11 @@ +.aca-locked-by { + .locked_by--icon { + font-size: 14px; + width: 14px; + height: 14px; + } + + .locked_by--name { + font-size: 12px; + } +} diff --git a/src/app/components/dl-custom-components/locked-by/locked-by.component.ts b/src/app/components/dl-custom-components/locked-by/locked-by.component.ts new file mode 100644 index 0000000000..6a01bb6227 --- /dev/null +++ b/src/app/components/dl-custom-components/locked-by/locked-by.component.ts @@ -0,0 +1,61 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Component, + Input, + OnInit, + ChangeDetectionStrategy, + ViewEncapsulation +} from '@angular/core'; + +import { NodeEntry } from '@alfresco/js-api'; + +@Component({ + selector: 'aca-locked-by', + template: ` + lock + {{ writeLockedBy() }} + `, + styleUrls: ['./locked-by.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, + host: { + class: 'aca-locked-by' + } +}) +export class LockByComponent implements OnInit { + @Input() + context: any; + + node: NodeEntry; + + constructor() {} + + ngOnInit() { + this.node = this.context.row.node; + } + + writeLockedBy() { + return ( + this.node && + this.node.entry.properties && + this.node.entry.properties['cm:lockOwner'] && + this.node.entry.properties['cm:lockOwner'].displayName + ); + } +} diff --git a/src/app/components/dl-custom-components/name-column/name-column.component.scss b/src/app/components/dl-custom-components/name-column/name-column.component.scss new file mode 100644 index 0000000000..d0969db211 --- /dev/null +++ b/src/app/components/dl-custom-components/name-column/name-column.component.scss @@ -0,0 +1,14 @@ +.aca-name-column-container { + aca-locked-by { + position: absolute; + top: 10px; + left: -4px; + display: flex; + align-items: center; + } +} + +.aca-custom-name-column { + display: flex; + align-items: center; +} diff --git a/src/app/components/dl-custom-components/name-column/name-column.component.spec.ts b/src/app/components/dl-custom-components/name-column/name-column.component.spec.ts new file mode 100644 index 0000000000..1668316818 --- /dev/null +++ b/src/app/components/dl-custom-components/name-column/name-column.component.spec.ts @@ -0,0 +1,108 @@ +/*! + * @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 . + */ + +import { CustomNameColumnComponent } from './name-column.component'; +import { DocumentListCustomComponentsModule } from '../document-list-custom-components.module'; +import { Actions } from '@ngrx/effects'; +import { StoreModule } from '@ngrx/store'; +import { TestBed } from '@angular/core/testing'; +import { CoreModule } from '@alfresco/adf-core'; + +describe('CustomNameColumnComponent', () => { + let fixture; + let component; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + CoreModule.forRoot(), + DocumentListCustomComponentsModule, + StoreModule.forRoot({ app: () => {} }, { initialState: {} }) + ], + providers: [Actions] + }); + + fixture = TestBed.createComponent(CustomNameColumnComponent); + component = fixture.componentInstance; + }); + + it('should not render lock element if file is not locked', () => { + component.context = { + row: { + node: { + entry: { + isFile: true, + id: 'nodeId' + } + } + } + }; + + fixture.detectChanges(); + + expect( + fixture.debugElement.nativeElement.querySelector('aca-locked-by') + ).toBe(null); + }); + + it('should not render lock element if node is not a file', () => { + component.context = { + row: { + node: { + entry: { + isFile: false, + id: 'nodeId' + } + } + } + }; + + fixture.detectChanges(); + + expect( + fixture.debugElement.nativeElement.querySelector('aca-locked-by') + ).toBe(null); + }); + + it('should render lock element if file is locked', () => { + component.context = { + row: { + node: { + entry: { + isFile: true, + id: 'nodeId', + properties: { 'cm:lockType': 'WRITE_LOCK' } + } + } + } + }; + + fixture.detectChanges(); + + expect( + fixture.debugElement.nativeElement.querySelector('aca-locked-by') + ).not.toBe(null); + }); +}); diff --git a/src/app/components/dl-custom-components/name-column/name-column.component.ts b/src/app/components/dl-custom-components/name-column/name-column.component.ts new file mode 100644 index 0000000000..cc6ab11a19 --- /dev/null +++ b/src/app/components/dl-custom-components/name-column/name-column.component.ts @@ -0,0 +1,90 @@ +/*! + * @license + * Copyright 2019 Alfresco Software, Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + Component, + Input, + OnInit, + ViewEncapsulation, + ChangeDetectorRef, + OnDestroy +} from '@angular/core'; +import { Actions, ofType } from '@ngrx/effects'; +import { EDIT_OFFLINE } from '../../../store/actions'; +import { NodeEntry } from '@alfresco/js-api'; +import { Subject } from 'rxjs'; +import { filter, takeUntil } from 'rxjs/operators'; +import { isLocked } from '../../../utils/node.utils'; + +@Component({ + selector: 'aca-custom-name-column', + template: ` +
+ + + + + +
+ `, + styleUrls: ['name-column.component.scss'], + encapsulation: ViewEncapsulation.None +}) +export class CustomNameColumnComponent implements OnInit, OnDestroy { + node: NodeEntry; + + @Input() + context: any; + + private onDestroy$: Subject = new Subject(); + + constructor(private cd: ChangeDetectorRef, private actions$: Actions) {} + + ngOnDestroy() { + this.onDestroy$.next(true); + this.onDestroy$.complete(); + } + + ngOnInit() { + this.node = this.context.row.node; + + this.actions$ + .pipe( + ofType(EDIT_OFFLINE), + filter(val => { + return this.node.entry.id === val.payload.entry.id; + }), + takeUntil(this.onDestroy$) + ) + .subscribe(() => { + this.cd.detectChanges(); + }); + } + + isFile() { + return this.node && this.node.entry && this.node.entry.isFile; + } + + isFileWriteLocked() { + return isLocked(this.node); + } +} diff --git a/src/app/components/favorite-libraries/favorite-libraries.component.html b/src/app/components/favorite-libraries/favorite-libraries.component.html index b4be5c2ad0..c8efa09f2c 100644 --- a/src/app/components/favorite-libraries/favorite-libraries.component.html +++ b/src/app/components/favorite-libraries/favorite-libraries.component.html @@ -1,75 +1,95 @@ + + + - - - + + + + + + - - + +
+ + + + + - - + + + + + + + + + - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - -
+ + +
- -
-
\ No newline at end of file + + + diff --git a/src/app/components/favorite-libraries/favorite-libraries.component.spec.ts b/src/app/components/favorite-libraries/favorite-libraries.component.spec.ts index 9c311719da..25c9d64e4a 100644 --- a/src/app/components/favorite-libraries/favorite-libraries.component.spec.ts +++ b/src/app/components/favorite-libraries/favorite-libraries.component.spec.ts @@ -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 @@ -29,8 +29,6 @@ import { UserPreferencesService } from '@alfresco/adf-core'; import { Router } from '@angular/router'; import { AlfrescoApiService, - TimeAgoPipe, - NodeNameTooltipPipe, NodeFavoriteDirective, DataTableComponent, AppConfigPipe @@ -39,7 +37,6 @@ import { DocumentListComponent } from '@alfresco/adf-content-services'; import { FavoriteLibrariesComponent } from './favorite-libraries.component'; import { AppTestingModule } from '../../testing/app-testing.module'; import { ContentApiService } from '../../services/content-api.service'; -import { ExperimentalDirective } from '../../directives/experimental.directive'; import { ContentManagementService } from '../../services/content-management.service'; import { EffectsModule } from '@ngrx/effects'; import { LibraryEffects, RouterEffects } from '../../store/effects'; @@ -72,13 +69,10 @@ describe('FavoriteLibrariesComponent', () => { ], declarations: [ DataTableComponent, - TimeAgoPipe, - NodeNameTooltipPipe, NodeFavoriteDirective, DocumentListComponent, FavoriteLibrariesComponent, - AppConfigPipe, - ExperimentalDirective + AppConfigPipe ], providers: [ContentManagementService, UserPreferencesService], schemas: [NO_ERRORS_SCHEMA] @@ -146,7 +140,7 @@ describe('FavoriteLibrariesComponent', () => { it('does not navigate when id is not passed', () => { spyOn(router, 'navigate').and.stub(); - component.navigateTo({ entry: { guid: 'guid' } }); + component.navigateTo({ entry: { guid: 'guid' } }); expect(router.navigate).toHaveBeenCalledWith(['libraries', 'libraryId']); }); diff --git a/src/app/components/favorite-libraries/favorite-libraries.component.ts b/src/app/components/favorite-libraries/favorite-libraries.component.ts index d76d317ca4..dbeb309751 100644 --- a/src/app/components/favorite-libraries/favorite-libraries.component.ts +++ b/src/app/components/favorite-libraries/favorite-libraries.component.ts @@ -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 { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; import { Component, OnInit } from '@angular/core'; import { Store } from '@ngrx/store'; -import { SiteEntry, FavoritePaging, Pagination } from 'alfresco-js-api'; +import { SiteEntry, FavoritePaging, Pagination } from '@alfresco/js-api'; import { AppExtensionService } from '../../extensions/extension.service'; import { ContentManagementService } from '../../services/content-management.service'; import { ContentApiService } from '../../services/content-api.service'; diff --git a/src/app/components/favorites/favorites.component.html b/src/app/components/favorites/favorites.component.html index 79c1bcb55e..e74033407a 100644 --- a/src/app/components/favorites/favorites.component.html +++ b/src/app/components/favorites/favorites.component.html @@ -1,81 +1,82 @@ - - - + - - - - - + + + + +
- - - - - - - - - - - + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - + + - - +
-