girder 5.0.19.dev60__tar.gz → 5.0.19.dev74__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.circleci/config.yml +27 -7
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.pre-commit-config.yaml +1 -0
- {girder-5.0.19.dev60/girder.egg-info → girder-5.0.19.dev74}/PKG-INFO +1 -1
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/playwright-teardown.ts +2 -2
- girder-5.0.19.dev74/girder/web/tests/spec/plugin_autojoin.spec.ts +100 -0
- girder-5.0.19.dev74/girder/web/tests/spec/plugin_hashsum_download.spec.ts +74 -0
- girder-5.0.19.dev74/girder/web/tests/spec/plugin_homepage.spec.ts +118 -0
- girder-5.0.19.dev74/girder/web/tests/spec/plugin_item_licenses.spec.ts +257 -0
- girder-5.0.19.dev74/girder/web/tests/spec/plugin_jobs.spec.ts +562 -0
- girder-5.0.19.dev74/girder/web/tests/spec/plugin_readme.spec.ts +52 -0
- girder-5.0.19.dev74/girder/web/tests/spec/plugin_terms.spec.ts +263 -0
- girder-5.0.19.dev74/girder/web/tests/spec/plugin_user_quota.spec.ts +434 -0
- girder-5.0.19.dev74/girder/web/tests/spec/utilities.spec.ts +434 -0
- girder-5.0.19.dev74/girder/web/tests/spec/version.spec.ts +60 -0
- girder-5.0.19.dev74/girder/web/tests/spec/widgets.spec.ts +290 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74/girder.egg-info}/PKG-INFO +1 -1
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder.egg-info/SOURCES.txt +5 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder.egg-info/scm_file_list.json +5 -0
- girder-5.0.19.dev74/girder.egg-info/scm_version.json +8 -0
- girder-5.0.19.dev60/girder/web/tests/spec/plugin_hashsum_download.spec.ts +0 -26
- girder-5.0.19.dev60/girder/web/tests/spec/plugin_homepage.spec.ts +0 -37
- girder-5.0.19.dev60/girder/web/tests/spec/plugin_item_licenses.spec.ts +0 -26
- girder-5.0.19.dev60/girder/web/tests/spec/plugin_readme.spec.ts +0 -24
- girder-5.0.19.dev60/girder/web/tests/spec/plugin_terms.spec.ts +0 -38
- girder-5.0.19.dev60/girder/web/tests/spec/plugin_user_quota.spec.ts +0 -39
- girder-5.0.19.dev60/girder.egg-info/scm_version.json +0 -8
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.circleci/Dockerfile +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.circleci/build_plugins.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.circleci/generatePyEnvChecksum.sh +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.circleci/publish_npm.sh +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.circleci/publish_pypi.sh +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.circleci/rabbitmq.conf +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.codecov.yml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.dockerignore +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.editorconfig +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.git-blame-ignore-revs +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.github/workflows/codespell.yml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.gitignore +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/.readthedocs.yml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/CHANGELOG.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/CMakeLists.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/CONTRIBUTING.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/Dockerfile +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/LICENSE +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/MANIFEST.in +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/README.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/clients/python/README.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/clients/python/girder_client/__init__.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/clients/python/girder_client/_jsonemitter.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/clients/python/girder_client/cli.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/clients/python/pyproject.toml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/clients/python/setup.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docker-compose.yml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/admin-docs.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/api-docs.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/build-docs.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/conf.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/configuration.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/dependencies.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/deployment.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/dev-installation.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/developer-cookbook.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/developer-docs.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/development.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/favicon.ico +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/images/dicom-viewer.png +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/index.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/license.png +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/list_env_settings.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/list_env_settings.yaml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/migration-guide.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/mount.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/plugin-development.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/plugins.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/python-client.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/requirements-docs.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/security.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/sftp.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/static/custom.css +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/user-docs.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/docs/user-guide.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/__init__.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/__init__.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/access.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/api_docs.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/api_main.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/describe.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/docs.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/filter_logging.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/rest.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/sftp.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/__init__.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/api_key.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/assetstore.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/collection.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/file.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/folder.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/group.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/item.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/resource.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/system.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/token.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/api/v1/user.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/asgi.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/cli/__init__.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/cli/mount.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/cli/serve.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/cli/sftpd.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/cli/shell.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/constants.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/events.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/exceptions.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/mail_templates/_footer.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/mail_templates/_header.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/mail_templates/accountApproval.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/mail_templates/accountApproved.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/mail_templates/emailVerification.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/mail_templates/groupInvite.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/mail_templates/temporaryAccess.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/__init__.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/api_key.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/assetstore.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/collection.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/file.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/folder.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/group.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/item.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/model_base.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/setting.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/token.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/upload.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/models/user.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/notification.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/plugin.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/settings.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/tasks.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/__init__.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/_cache.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/_hash_state.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/abstract_assetstore_adapter.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/acl_mixin.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/assetstore_utilities.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/config.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/error.mako +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/filesystem_assetstore_adapter.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/mail_utils.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/model_importer.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/path.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/progress.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/s3_assetstore_adapter.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/search.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/server.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/setting_utilities.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/system.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/webroot.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/utility/ziputil.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/.env.development +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/.gitignore +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/.prettierrc.json +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/README.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/Girder_Favicon.png +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/Girder_Mark.png +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/fontello-BGLM866c.svg +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/fontello-CMxI46LA.eot +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/fontello-Ddaw8Z2O.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/fontello-KuItqCW9.ttf +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/fontello-_lT35XxX.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/glyphicons-halflings-regular-BKjkU69z.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/glyphicons-halflings-regular-BUJKDMgK.eot +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/glyphicons-halflings-regular-CSehLiBc.svg +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/glyphicons-halflings-regular-DrwTMapi.ttf +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/glyphicons-halflings-regular-DzqM6ju8.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/index-C3KtNRrl.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/index-C3KtNRrl.js.map +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/index-DFhDyJFH.css +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/jsoneditor-icons-CIlYC0TY.svg +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-300-B6tDWRxp.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-300-DZbNTRe6.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-300italic-DLsXqxhU.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-300italic-Dfz31Up5.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-400-D5zbb_EN.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-400-DLgeRt71.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-400italic-DpGQ6Ktj.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-400italic-UJbezL8h.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-600-CCvT4JHQ.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-600-DHWfDY-G.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-600italic-X8kCjSq_.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-600italic-slqXzGub.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-700-CsbQbrjx.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-700-DNl7WOH5.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-700italic-BtE7VvhE.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-700italic-hc2P_kZo.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-800-CbJOM4_m.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-800-XaYTAPrv.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-800italic-DqvYew-K.woff +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/assets/open-sans-latin-800italic-JIGkTxpX.woff2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/index.html +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/auth.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/constants.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/dialog.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/events.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/index.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/main.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/misc.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/pluginUtils.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/rest.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/router.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/routes.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/version.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/src/src/vite-env.d.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/swagger-ui/swagger-ui-bundle.js +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/dist/swagger-ui/swagger-ui.css +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/env.d.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/playwright.config.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/coverage.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/playwright-setup.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/server.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/admin.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/browser.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/collection.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/collectionBaseClass.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/customWidgets.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data/README.md +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data/fake.jpg +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data/nomime.dat +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data/slicer_cli_web_multiple_test.xml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data/slicer_cli_web_test.xml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data/ten_byte_file.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data/testFile.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data/testFile2 +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/data.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/emptyLayout.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/file_upload.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/folder.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/group.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/item.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/model.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_authorized_upload.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web_config_view.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web_container_view.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web_item_selector.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web_panel_group.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web_parser.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web_task.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web_widget_model.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_slicer_cli_web_widget_view.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/plugin_thumbnails.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/routing.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/setApi.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/setting_show_download.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/sortWidget.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/swagger.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/spec/user.spec.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/web/tests/util.ts +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/worker_plugin.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder/wsgi.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder.egg-info/dependency_links.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder.egg-info/entry_points.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder.egg-info/not-zip-safe +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder.egg-info/requires.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/girder.egg-info/top_level.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/jsdoc.json +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/package-lock.json +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/package.json +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pyproject.toml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/LICENSE +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/MANIFEST.in +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/pyproject.toml +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/pytest_girder/__init__.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/pytest_girder/assertions.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/pytest_girder/fixtures.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/pytest_girder/plugin.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/pytest_girder/plugin_registry.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/pytest_girder/utils.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/pytest_girder/web_client.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/pytest_girder/setup.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/requirements-dev.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/scripts/midas/README.rst +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/scripts/midas/migrate.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/scripts/midas/requirements.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/scripts/midas/walk_girder.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/scripts/midas/walk_midas.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/scripts/publicNames.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/scripts/publicNames.txt +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/scripts/test_names.sh +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/setup.cfg +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/setup.py +0 -0
- {girder-5.0.19.dev60 → girder-5.0.19.dev74}/tox.ini +0 -0
|
@@ -175,6 +175,11 @@ jobs:
|
|
|
175
175
|
web-test:
|
|
176
176
|
executor: py3-mongo
|
|
177
177
|
resource_class: large
|
|
178
|
+
parameters:
|
|
179
|
+
browser:
|
|
180
|
+
description: "Playwright project / browser to run the web tests against"
|
|
181
|
+
type: enum
|
|
182
|
+
enum: [chromium, firefox]
|
|
178
183
|
steps:
|
|
179
184
|
- checkout:
|
|
180
185
|
path: girder
|
|
@@ -188,20 +193,26 @@ jobs:
|
|
|
188
193
|
- build-plugins
|
|
189
194
|
- run:
|
|
190
195
|
name: Install playwright browser dependencies
|
|
191
|
-
command:
|
|
196
|
+
command: npx playwright install --with-deps << parameters.browser >>
|
|
192
197
|
working_directory: girder/girder/web
|
|
193
198
|
- run:
|
|
194
|
-
name: Test @girder/core
|
|
195
|
-
command: npm run test
|
|
199
|
+
name: Test @girder/core (<< parameters.browser >>)
|
|
200
|
+
command: npm run test -- --project=<< parameters.browser >>
|
|
196
201
|
working_directory: girder/girder/web
|
|
197
202
|
environment:
|
|
198
203
|
PLAYWRIGHT_WORKERS: 4
|
|
204
|
+
GIRDER_TEST_COVERAGE_DIR: ../../build/test/coverage/<< parameters.browser >>
|
|
205
|
+
GIRDER_TEST_COVERAGE_FILE: cobertura-coverage.xml
|
|
199
206
|
- store_artifacts:
|
|
200
207
|
path: girder/girder/web/coverage/report
|
|
201
|
-
destination: coverage
|
|
208
|
+
destination: coverage-<< parameters.browser >>
|
|
202
209
|
- store_artifacts:
|
|
203
210
|
path: girder/girder/web/test-results
|
|
204
|
-
destination: test-results
|
|
211
|
+
destination: test-results-<< parameters.browser >>
|
|
212
|
+
- persist_to_workspace:
|
|
213
|
+
root: /home/circleci/project
|
|
214
|
+
paths:
|
|
215
|
+
- girder/build/test/coverage/<< parameters.browser >>
|
|
205
216
|
|
|
206
217
|
integration-test:
|
|
207
218
|
executor: machine
|
|
@@ -316,7 +327,7 @@ jobs:
|
|
|
316
327
|
working_directory: girder
|
|
317
328
|
- run:
|
|
318
329
|
name: Upload coverage
|
|
319
|
-
command: ./codecov --disable search pycov gcov --root girder --required --file build/test/coverage/py_coverage.xml build/test/coverage/cobertura-coverage.xml
|
|
330
|
+
command: ./codecov --disable search pycov gcov --root girder --required --file build/test/coverage/py_coverage.xml build/test/coverage/chromium/cobertura-coverage.xml build/test/coverage/firefox/cobertura-coverage.xml
|
|
320
331
|
working_directory: girder
|
|
321
332
|
|
|
322
333
|
dockers:
|
|
@@ -424,6 +435,14 @@ workflows:
|
|
|
424
435
|
tags:
|
|
425
436
|
only: /^v[0-9]+.*/
|
|
426
437
|
- web-test:
|
|
438
|
+
name: web-test-chromium
|
|
439
|
+
browser: chromium
|
|
440
|
+
filters:
|
|
441
|
+
tags:
|
|
442
|
+
only: /^v[0-9]+.*/
|
|
443
|
+
- web-test:
|
|
444
|
+
name: web-test-firefox
|
|
445
|
+
browser: firefox
|
|
427
446
|
filters:
|
|
428
447
|
tags:
|
|
429
448
|
only: /^v[0-9]+.*/
|
|
@@ -435,7 +454,8 @@ workflows:
|
|
|
435
454
|
requires:
|
|
436
455
|
- server-pytest-test
|
|
437
456
|
- server-legacy-test
|
|
438
|
-
- web-test
|
|
457
|
+
- web-test-chromium
|
|
458
|
+
- web-test-firefox
|
|
439
459
|
- integration-test
|
|
440
460
|
filters:
|
|
441
461
|
tags:
|
|
@@ -33,7 +33,7 @@ export default async (_config: PlaywrightTestConfig) => {
|
|
|
33
33
|
|
|
34
34
|
report.execute(context);
|
|
35
35
|
|
|
36
|
-
const outputDir = '../../build/test/coverage';
|
|
36
|
+
const outputDir = process.env.GIRDER_TEST_COVERAGE_DIR || '../../build/test/coverage';
|
|
37
37
|
await fs.mkdir(outputDir, { recursive: true });
|
|
38
38
|
const contextXml = libReport.createContext({
|
|
39
39
|
dir: outputDir,
|
|
@@ -41,7 +41,7 @@ export default async (_config: PlaywrightTestConfig) => {
|
|
|
41
41
|
coverageMap,
|
|
42
42
|
});
|
|
43
43
|
const xmlReport = reports.create('cobertura', {
|
|
44
|
-
file: 'cobertura-coverage.xml',
|
|
44
|
+
file: process.env.GIRDER_TEST_COVERAGE_FILE || 'cobertura-coverage.xml',
|
|
45
45
|
skipEmpty: false,
|
|
46
46
|
});
|
|
47
47
|
xmlReport.execute(contextXml);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { expect, Page, test } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
import { setupServer } from '../server';
|
|
4
|
+
import { createUser, waitForIdlePage } from '../util';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Ported from 3.x-maintenance: plugins/autojoin/plugin_tests/autojoinSpec.js
|
|
8
|
+
* Tests for the Auto Join plugin's configuration page and its effect on new
|
|
9
|
+
* users.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Navigate to the groups list page.
|
|
14
|
+
*/
|
|
15
|
+
async function gotoGroupsPage(page: Page) {
|
|
16
|
+
await page.locator('a.g-nav-link[g-target="groups"]').click();
|
|
17
|
+
await expect(page.locator('.g-group-search-form .g-search-field')).toBeVisible();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Create a private group and wait for its page to load. Assumes the user is
|
|
22
|
+
* logged in.
|
|
23
|
+
*/
|
|
24
|
+
async function createGroup(page: Page, name: string) {
|
|
25
|
+
await gotoGroupsPage(page);
|
|
26
|
+
await expect(page.locator('.g-group-create-button')).toBeVisible();
|
|
27
|
+
await page.locator('.g-group-create-button').click();
|
|
28
|
+
await expect(page.locator('#g-name')).toBeVisible();
|
|
29
|
+
await page.locator('#g-name').fill(name);
|
|
30
|
+
await page.locator('.g-save-group').click();
|
|
31
|
+
await waitForIdlePage(page);
|
|
32
|
+
await expect(page.locator('.g-group-name')).toHaveText(name);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Navigate to the Auto Join plugin configuration page.
|
|
37
|
+
*/
|
|
38
|
+
async function gotoAutojoinConfig(page: Page) {
|
|
39
|
+
await page.locator('a.g-nav-link[g-target="admin"]').click();
|
|
40
|
+
await page.locator('.g-plugins-config').click();
|
|
41
|
+
const configLink = page.locator('.g-plugin-list-item[data-name="autojoin"] a.g-plugin-config-link');
|
|
42
|
+
await expect(configLink).toBeVisible();
|
|
43
|
+
await configLink.click();
|
|
44
|
+
// Wait for the group collection to populate the group select.
|
|
45
|
+
await expect(page.locator('#g-autojoin-group > option')).toHaveCount(4);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Fill out and submit the "add rule" row of the Auto Join configuration page.
|
|
50
|
+
*/
|
|
51
|
+
async function addRule(page: Page, pattern: string, groupName: string, level: string) {
|
|
52
|
+
await page.locator('#g-autojoin-pattern').fill(pattern);
|
|
53
|
+
await page.locator('#g-autojoin-group').selectOption({ label: groupName });
|
|
54
|
+
await page.locator('#g-autojoin-level').selectOption(level);
|
|
55
|
+
await page.locator('#g-autojoin-add').click();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
test.describe('Test the auto join plugin', () => {
|
|
59
|
+
setupServer();
|
|
60
|
+
|
|
61
|
+
test('configure auto join rules', async ({ page }) => {
|
|
62
|
+
await createUser(page, 'admin', 'admin@girder.test', 'Joe', 'Admin', 'password');
|
|
63
|
+
|
|
64
|
+
await createGroup(page, 'group1');
|
|
65
|
+
await createGroup(page, 'group2');
|
|
66
|
+
await createGroup(page, 'group3');
|
|
67
|
+
|
|
68
|
+
await gotoAutojoinConfig(page);
|
|
69
|
+
|
|
70
|
+
await addRule(page, '@girder1.test', 'group1', '2');
|
|
71
|
+
await addRule(page, '@girder2.test', 'group2', '1');
|
|
72
|
+
await addRule(page, '@girder2.test', 'group3', '0');
|
|
73
|
+
|
|
74
|
+
await expect(page.locator('.g-autojoin-container tbody tr')).toHaveCount(3);
|
|
75
|
+
await expect(page.locator('.g-autojoin-container')).toContainText('@girder1.test');
|
|
76
|
+
await expect(page.locator('.g-autojoin-container')).toContainText('@girder2.test');
|
|
77
|
+
|
|
78
|
+
await page.locator('#g-autojoin-save').click();
|
|
79
|
+
await expect(page.locator('#g-alerts-container')).toContainText('Settings saved');
|
|
80
|
+
await waitForIdlePage(page);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test('auto join a user whose email matches the girder2 rule', async ({ page }) => {
|
|
84
|
+
await createUser(page, 'user1', 'user1@girder2.test', 'Joe', 'User', 'password');
|
|
85
|
+
|
|
86
|
+
await gotoGroupsPage(page);
|
|
87
|
+
await expect(page.locator('.g-group-title', { hasText: 'group1' })).toHaveCount(0);
|
|
88
|
+
await expect(page.locator('.g-group-title', { hasText: 'group2' })).toHaveCount(1);
|
|
89
|
+
await expect(page.locator('.g-group-title', { hasText: 'group3' })).toHaveCount(1);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('auto join a user whose email matches the girder1 rule', async ({ page }) => {
|
|
93
|
+
await createUser(page, 'user2', 'user2@girder1.test', 'Joe', 'User', 'password');
|
|
94
|
+
|
|
95
|
+
await gotoGroupsPage(page);
|
|
96
|
+
await expect(page.locator('.g-group-title', { hasText: 'group1' })).toHaveCount(1);
|
|
97
|
+
await expect(page.locator('.g-group-title', { hasText: 'group2' })).toHaveCount(0);
|
|
98
|
+
await expect(page.locator('.g-group-title', { hasText: 'group3' })).toHaveCount(0);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
|
|
4
|
+
import { Page, expect, test } from '@playwright/test';
|
|
5
|
+
|
|
6
|
+
import { setupServer } from '../server';
|
|
7
|
+
import { createUser, upload, waitForIdlePage } from '../util';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Make a REST request from within the page context and await its result.
|
|
14
|
+
*/
|
|
15
|
+
async function asyncRestRequest(page: Page, opts: Record<string, unknown>) {
|
|
16
|
+
return await page.evaluate((requestOpts) => {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
// @ts-ignore - window.girder is available at runtime
|
|
19
|
+
window.girder.rest.restRequest(requestOpts).done((resp: unknown) => {
|
|
20
|
+
resolve(resp);
|
|
21
|
+
}).fail((resp: unknown) => {
|
|
22
|
+
reject(resp);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}, opts);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
test.describe('Test the hashsum download front-end', () => {
|
|
29
|
+
setupServer();
|
|
30
|
+
|
|
31
|
+
test('verify presence of key file', async ({ page }) => {
|
|
32
|
+
await createUser(page, 'admin');
|
|
33
|
+
await page.locator('#g-app-header-container').getByText('admin').click();
|
|
34
|
+
await page.locator('a.g-my-folders').click();
|
|
35
|
+
await page.getByRole('link', { name: ' Private ' }).click();
|
|
36
|
+
await upload(page, path.join(__dirname, 'data', 'ten_byte_file.txt'));
|
|
37
|
+
|
|
38
|
+
await page.getByRole('link', { name: ' ten_byte_file.txt' }).click();
|
|
39
|
+
await page.getByTitle('Show info').click();
|
|
40
|
+
await expect(page.locator('input.g-hash-textbox').first()).toHaveValue('ff3245abe317049ed1b8aa7aa2f4c4dcb8bf86f083ed67eb26b43e2fbe3ba8fdf759f9e2f46fcf2a06c2dfeddf0cedcd41a68034cd618b880785b34f759d1a69')
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test.describe('Test the hashsum download configuration page', () => {
|
|
45
|
+
setupServer();
|
|
46
|
+
|
|
47
|
+
test('enable automatic checksum computation', async ({ page }) => {
|
|
48
|
+
await createUser(page, 'admin');
|
|
49
|
+
|
|
50
|
+
// Navigate to the plugin's admin settings page.
|
|
51
|
+
await page.locator('a.g-nav-link[g-target="admin"]').click();
|
|
52
|
+
await page.locator('.g-plugins-config').click();
|
|
53
|
+
const configLink = page.locator('.g-plugin-list-item[data-name="hashsum_download"] a.g-plugin-config-link');
|
|
54
|
+
await expect(configLink).toBeVisible();
|
|
55
|
+
await configLink.click();
|
|
56
|
+
|
|
57
|
+
const autoCompute = page.locator('#g-hashsum-download-auto-compute');
|
|
58
|
+
await expect(autoCompute).toBeVisible();
|
|
59
|
+
await expect(autoCompute).not.toBeChecked();
|
|
60
|
+
await autoCompute.check();
|
|
61
|
+
|
|
62
|
+
await page.locator('#g-hashsum-download-config-form input[type="submit"]').click();
|
|
63
|
+
await expect(page.locator('#g-alerts-container')).toContainText('Settings saved');
|
|
64
|
+
await waitForIdlePage(page);
|
|
65
|
+
|
|
66
|
+
// Verify that the setting was persisted on the server.
|
|
67
|
+
const settings = await asyncRestRequest(page, {
|
|
68
|
+
url: '/system/setting',
|
|
69
|
+
method: 'GET',
|
|
70
|
+
data: { list: JSON.stringify(['hashsum_download.auto_compute']) },
|
|
71
|
+
}) as Record<string, unknown>;
|
|
72
|
+
expect(settings['hashsum_download.auto_compute']).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Locator, Page, expect, test } from '@playwright/test';
|
|
2
|
+
|
|
3
|
+
import { setupServer } from '../server';
|
|
4
|
+
import { createUser, login, logout } from '../util';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Ported from 3.x-maintenance: plugins/homepage/plugin_tests/homepageSpec.js
|
|
8
|
+
* Tests for the Homepage plugin's configuration page and its effect on the
|
|
9
|
+
* front page.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const markdown =
|
|
13
|
+
'It\'s very easy to make some words **bold** and other words *italic* with ' +
|
|
14
|
+
'Markdown. You can even [link to Girder!](https://girder.readthedocs.io/)';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Assert that the given container renders the expected markdown content.
|
|
18
|
+
*/
|
|
19
|
+
async function expectMarkdown(container: Locator) {
|
|
20
|
+
await expect(container.locator('p')).toContainText("It's very easy");
|
|
21
|
+
await expect(container.locator('strong')).toContainText('bold');
|
|
22
|
+
await expect(container.locator('em')).toContainText('italic');
|
|
23
|
+
await expect(container.locator('a[href="https://girder.readthedocs.io/"]')).toContainText('link to Girder!');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Navigate to the Homepage plugin configuration page.
|
|
28
|
+
*/
|
|
29
|
+
async function gotoHomepageConfig(page: Page) {
|
|
30
|
+
await page.locator('a.g-nav-link[g-target="admin"]').click();
|
|
31
|
+
await page.locator('.g-plugins-config').click();
|
|
32
|
+
const configLink = page.locator('.g-plugin-list-item[data-name="homepage"] a.g-plugin-config-link');
|
|
33
|
+
await expect(configLink).toBeVisible();
|
|
34
|
+
await configLink.click();
|
|
35
|
+
await expect(page.locator('.g-homepage-container')).toBeVisible();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Navigate back to the front page via the app title.
|
|
40
|
+
*/
|
|
41
|
+
async function gotoFrontPage(page: Page) {
|
|
42
|
+
await page.locator('.g-app-title').click();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Save the homepage configuration form and wait for the success alert.
|
|
47
|
+
*/
|
|
48
|
+
async function saveHomepageConfig(page: Page) {
|
|
49
|
+
await page.locator('#g-homepage-form input[type="submit"]').click();
|
|
50
|
+
await expect(page.locator('#g-alerts-container')).toContainText('Settings saved');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
test.describe('Test the homepage front-end', () => {
|
|
54
|
+
setupServer();
|
|
55
|
+
|
|
56
|
+
test('exercise homepage markdown customization', async ({ page }) => {
|
|
57
|
+
await createUser(page, 'admin', 'admin@girder.test', 'Mark', 'Down', 'password');
|
|
58
|
+
|
|
59
|
+
await gotoHomepageConfig(page);
|
|
60
|
+
|
|
61
|
+
// Write markdown and verify the preview renders it.
|
|
62
|
+
await page.locator('.g-homepage-container textarea.g-markdown-text').fill(markdown);
|
|
63
|
+
await page.locator('.g-homepage-container a.g-preview-link').click();
|
|
64
|
+
await expectMarkdown(page.locator('.g-homepage-container .g-markdown-preview'));
|
|
65
|
+
|
|
66
|
+
await saveHomepageConfig(page);
|
|
67
|
+
|
|
68
|
+
// The front page body is completely replaced by the rendered markdown.
|
|
69
|
+
await gotoFrontPage(page);
|
|
70
|
+
await expectMarkdown(page.locator('#g-app-body-container'));
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('set, preview, and save welcome text and branding', async ({ page }) => {
|
|
74
|
+
await login(page, 'admin', 'password');
|
|
75
|
+
|
|
76
|
+
await gotoHomepageConfig(page);
|
|
77
|
+
|
|
78
|
+
// Clear the full-page markdown so the branding settings are used.
|
|
79
|
+
await page.locator('.g-homepage-container textarea.g-markdown-text').fill('');
|
|
80
|
+
await page.locator('.g-homepage-container a.g-preview-link').click();
|
|
81
|
+
await expect(page.locator('.g-homepage-container .g-markdown-preview')).toHaveText('Nothing to show');
|
|
82
|
+
|
|
83
|
+
// Set header, subheader, and welcome text.
|
|
84
|
+
await page.locator('#g-homepage-header').fill('Header');
|
|
85
|
+
await page.locator('#g-homepage-subheader').fill('Subheader');
|
|
86
|
+
const welcomeText = page.locator('.g-homepage-welcome-text-container textarea.g-markdown-text');
|
|
87
|
+
await welcomeText.fill(markdown);
|
|
88
|
+
await page.locator('.g-homepage-welcome-text-container a.g-preview-link').click();
|
|
89
|
+
await expectMarkdown(page.locator('.g-homepage-welcome-text-container .g-markdown-preview'));
|
|
90
|
+
|
|
91
|
+
await saveHomepageConfig(page);
|
|
92
|
+
|
|
93
|
+
// The branded front page shows the configured header/subheader and the
|
|
94
|
+
// welcome text rendered as markdown.
|
|
95
|
+
await gotoFrontPage(page);
|
|
96
|
+
await expect(page.locator('.g-frontpage-title')).toHaveText('Header');
|
|
97
|
+
await expect(page.locator('.g-frontpage-subtitle')).toHaveText('Subheader');
|
|
98
|
+
await expectMarkdown(page.locator('.g-frontpage-welcome-text-content'));
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('settings persist after reload and are visible anonymously', async ({ page }) => {
|
|
102
|
+
await login(page, 'admin', 'password');
|
|
103
|
+
|
|
104
|
+
// Configure the full-page markdown replacement.
|
|
105
|
+
await gotoHomepageConfig(page);
|
|
106
|
+
await page.locator('.g-homepage-container textarea.g-markdown-text').fill(markdown);
|
|
107
|
+
await saveHomepageConfig(page);
|
|
108
|
+
|
|
109
|
+
// Re-open the config page and verify the markdown was persisted.
|
|
110
|
+
await gotoHomepageConfig(page);
|
|
111
|
+
await expect(page.locator('.g-homepage-container textarea.g-markdown-text')).toHaveValue(markdown);
|
|
112
|
+
|
|
113
|
+
// Log out and verify the markdown still renders to anonymous users.
|
|
114
|
+
await logout(page);
|
|
115
|
+
await gotoFrontPage(page);
|
|
116
|
+
await expectMarkdown(page.locator('#g-app-body-container'));
|
|
117
|
+
});
|
|
118
|
+
});
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
|
|
4
|
+
import { Locator, Page, expect, test } from '@playwright/test';
|
|
5
|
+
|
|
6
|
+
import { setupServer } from '../server';
|
|
7
|
+
import { createUser, login, waitForDialog, waitForIdlePage } from '../util';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Ported from 3.x-maintenance:
|
|
11
|
+
* plugins/item_licenses/plugin_tests/itemLicensesSpec.js
|
|
12
|
+
*
|
|
13
|
+
* Tests the item_licenses plugin: selecting a license when creating/editing an
|
|
14
|
+
* item or uploading a file, viewing the license on the item page, and the
|
|
15
|
+
* behavior of the "Unspecified" license.
|
|
16
|
+
*
|
|
17
|
+
* The original spec was a single sequential Jasmine describe. This port keeps
|
|
18
|
+
* the same sequence in a serial Playwright describe: the server and database
|
|
19
|
+
* are shared across the whole describe, admin is registered in the first test,
|
|
20
|
+
* and later tests log back in as needed.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
24
|
+
const __dirname = path.dirname(__filename);
|
|
25
|
+
|
|
26
|
+
const ADMIN = {
|
|
27
|
+
login: 'admin',
|
|
28
|
+
email: 'admin@girder.test',
|
|
29
|
+
firstName: 'Admin',
|
|
30
|
+
lastName: 'User',
|
|
31
|
+
password: 'password!',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const MIT_LICENSE = 'The MIT License (MIT)';
|
|
35
|
+
const APACHE_LICENSE = 'Apache License 2';
|
|
36
|
+
|
|
37
|
+
/** The number of license options: 12 code + 9 content, plus "Unspecified". */
|
|
38
|
+
const NUM_LICENSES = 22;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Navigate to the admin's folder list.
|
|
42
|
+
*/
|
|
43
|
+
async function gotoMyFolders(page: Page) {
|
|
44
|
+
await expect(page.locator('.g-user-dropdown-link')).toBeVisible();
|
|
45
|
+
await page.locator('.g-user-dropdown-link').click();
|
|
46
|
+
await page.locator('a.g-my-folders').click();
|
|
47
|
+
await expect(page.locator('a.g-folder-list-link', { hasText: 'Public' })).toBeVisible();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Open a folder of the current user's page by name.
|
|
52
|
+
*/
|
|
53
|
+
async function openFolder(page: Page, name: string) {
|
|
54
|
+
await expect(page.locator('a.g-folder-list-link', { hasText: name })).toBeVisible();
|
|
55
|
+
await page.locator('a.g-folder-list-link', { hasText: name }).click();
|
|
56
|
+
await expect(page.locator('.g-folder-actions-button:visible')).toHaveCount(1);
|
|
57
|
+
await waitForIdlePage(page);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Assert that the license select in the currently open dialog has the expected
|
|
62
|
+
* options and selected value.
|
|
63
|
+
*/
|
|
64
|
+
async function expectLicenseSelect(select: Locator, currentLicense: string) {
|
|
65
|
+
await expect(select).toBeVisible();
|
|
66
|
+
await expect(select.locator('optgroup')).toHaveCount(2);
|
|
67
|
+
await expect(select.locator('option')).toHaveCount(NUM_LICENSES);
|
|
68
|
+
await expect(select).toHaveValue(currentLicense);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Open the "Create item here" dialog from the folder actions menu.
|
|
73
|
+
*/
|
|
74
|
+
async function openCreateItemDialog(page: Page) {
|
|
75
|
+
await page.locator('.g-folder-actions-button:visible').click();
|
|
76
|
+
await expect(page.locator('a.g-create-item:visible')).toHaveCount(1);
|
|
77
|
+
await page.locator('a.g-create-item:visible').click();
|
|
78
|
+
await expect.poll(() => page.evaluate(() => window.location.hash)).toContain('dialog=itemcreate');
|
|
79
|
+
await waitForDialog(page);
|
|
80
|
+
await expect(page.locator('.g-save-item:visible')).toHaveText('Create');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Open the item edit dialog from the item actions menu.
|
|
85
|
+
*/
|
|
86
|
+
async function openEditItemDialog(page: Page) {
|
|
87
|
+
await expect(page.locator('.g-item-actions-button:visible')).toHaveCount(1);
|
|
88
|
+
await page.locator('.g-item-actions-button:visible').click();
|
|
89
|
+
await expect(page.locator('.g-edit-item:visible')).toHaveCount(1);
|
|
90
|
+
await page.locator('.g-edit-item:visible').click();
|
|
91
|
+
await expect.poll(() => page.evaluate(() => window.location.hash)).toContain('dialog=itemedit');
|
|
92
|
+
await waitForDialog(page);
|
|
93
|
+
await expect(page.locator('#g-name')).not.toHaveValue('');
|
|
94
|
+
await expect(page.locator('.g-save-item:visible')).toHaveText('Save');
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Open an item from the current folder listing and return once the item page's
|
|
99
|
+
* license field has loaded.
|
|
100
|
+
*/
|
|
101
|
+
async function openItem(page: Page, name: string) {
|
|
102
|
+
await expect(page.locator('a.g-item-list-link', { hasText: name })).toHaveCount(1);
|
|
103
|
+
await page.locator('a.g-item-list-link', { hasText: name }).click();
|
|
104
|
+
await expect(page.locator('.g-item-name')).toHaveText(name);
|
|
105
|
+
await expect(page.locator('.g-item-license')).toHaveCount(1);
|
|
106
|
+
await waitForIdlePage(page);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Navigate back to the Public folder listing via the breadcrumb.
|
|
111
|
+
*/
|
|
112
|
+
async function backToPublicFolder(page: Page) {
|
|
113
|
+
await expect(page.locator('a.g-item-breadcrumb-link', { hasText: 'Public' })).toBeVisible();
|
|
114
|
+
await page.locator('a.g-item-breadcrumb-link', { hasText: 'Public' }).click();
|
|
115
|
+
await expect(page.locator('.g-folder-actions-button:visible')).toHaveCount(1);
|
|
116
|
+
await waitForIdlePage(page);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
test.describe('Test the item licenses front-end', () => {
|
|
120
|
+
setupServer();
|
|
121
|
+
|
|
122
|
+
test('register the admin user', async ({ page }) => {
|
|
123
|
+
await createUser(page, ADMIN.login, ADMIN.email, ADMIN.firstName, ADMIN.lastName, ADMIN.password);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('create an item with a license', async ({ page }) => {
|
|
127
|
+
await login(page, ADMIN.login, ADMIN.password);
|
|
128
|
+
await gotoMyFolders(page);
|
|
129
|
+
await openFolder(page, 'Public');
|
|
130
|
+
await openCreateItemDialog(page);
|
|
131
|
+
|
|
132
|
+
// "Unspecified" is selected by default.
|
|
133
|
+
await expectLicenseSelect(page.locator('#g-license'), '');
|
|
134
|
+
|
|
135
|
+
await page.locator('input#g-name').fill('Test Item');
|
|
136
|
+
await page.locator('#g-license').selectOption(MIT_LICENSE);
|
|
137
|
+
await page.locator('.g-save-item').click();
|
|
138
|
+
await waitForIdlePage(page);
|
|
139
|
+
|
|
140
|
+
await openItem(page, 'Test Item');
|
|
141
|
+
await expect(page.locator('.g-item-license')).toContainText(MIT_LICENSE);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('edit an item license', async ({ page }) => {
|
|
145
|
+
await login(page, ADMIN.login, ADMIN.password);
|
|
146
|
+
await gotoMyFolders(page);
|
|
147
|
+
await openFolder(page, 'Public');
|
|
148
|
+
await openItem(page, 'Test Item');
|
|
149
|
+
|
|
150
|
+
await openEditItemDialog(page);
|
|
151
|
+
// The item's current license is selected by default.
|
|
152
|
+
await expectLicenseSelect(page.locator('#g-license'), MIT_LICENSE);
|
|
153
|
+
|
|
154
|
+
await page.locator('#g-license').selectOption(APACHE_LICENSE);
|
|
155
|
+
await page.locator('.g-save-item').click();
|
|
156
|
+
await waitForIdlePage(page);
|
|
157
|
+
|
|
158
|
+
await expect(page.locator('.g-item-license')).toContainText(APACHE_LICENSE);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test('upload into an item does not show the license widget', async ({ page }) => {
|
|
162
|
+
await login(page, ADMIN.login, ADMIN.password);
|
|
163
|
+
await gotoMyFolders(page);
|
|
164
|
+
await openFolder(page, 'Public');
|
|
165
|
+
await openItem(page, 'Test Item');
|
|
166
|
+
|
|
167
|
+
await expect(page.locator('.g-upload-into-item:visible')).toHaveCount(1);
|
|
168
|
+
await page.locator('.g-upload-into-item:visible').click();
|
|
169
|
+
await expect.poll(() => page.evaluate(() => window.location.hash)).toContain('dialog=upload');
|
|
170
|
+
await waitForDialog(page);
|
|
171
|
+
await expect(page.locator('.g-start-upload:visible')).toContainText('Start Upload');
|
|
172
|
+
|
|
173
|
+
// Uploading into a specific item must not offer a license selection.
|
|
174
|
+
await expect(page.locator('#g-license')).toHaveCount(0);
|
|
175
|
+
|
|
176
|
+
// Close the dialog and return to the folder listing.
|
|
177
|
+
await page.locator('#g-dialog-container .modal-header .close').click();
|
|
178
|
+
await expect(page.locator('#g-dialog-container')).toBeHidden();
|
|
179
|
+
await backToPublicFolder(page);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('upload a file into a folder, specifying a license', async ({ page }) => {
|
|
183
|
+
await login(page, ADMIN.login, ADMIN.password);
|
|
184
|
+
await gotoMyFolders(page);
|
|
185
|
+
await openFolder(page, 'Public');
|
|
186
|
+
|
|
187
|
+
await page.locator('.g-upload-here-button:visible').click();
|
|
188
|
+
await expect.poll(() => page.evaluate(() => window.location.hash)).toContain('dialog=upload');
|
|
189
|
+
await waitForDialog(page);
|
|
190
|
+
await expect(page.locator('.g-start-upload:visible')).toContainText('Start Upload');
|
|
191
|
+
|
|
192
|
+
// Uploading into a folder offers the license selection widget.
|
|
193
|
+
await expectLicenseSelect(page.locator('#g-license'), '');
|
|
194
|
+
await page.locator('#g-license').selectOption(APACHE_LICENSE);
|
|
195
|
+
|
|
196
|
+
await page.locator('#g-files').setInputFiles(path.join(__dirname, 'data', 'testFile.txt'));
|
|
197
|
+
await expect(page.locator('.g-start-upload')).toBeEnabled();
|
|
198
|
+
await page.locator('.g-start-upload').click();
|
|
199
|
+
await waitForIdlePage(page);
|
|
200
|
+
await expect(page.locator('#g-dialog-container')).toBeHidden();
|
|
201
|
+
|
|
202
|
+
await openItem(page, 'testFile.txt');
|
|
203
|
+
await expect(page.locator('.g-item-license')).toContainText(APACHE_LICENSE);
|
|
204
|
+
|
|
205
|
+
await backToPublicFolder(page);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test('create an item with an unspecified license', async ({ page }) => {
|
|
209
|
+
await login(page, ADMIN.login, ADMIN.password);
|
|
210
|
+
await gotoMyFolders(page);
|
|
211
|
+
await openFolder(page, 'Public');
|
|
212
|
+
await openCreateItemDialog(page);
|
|
213
|
+
|
|
214
|
+
await expectLicenseSelect(page.locator('#g-license'), '');
|
|
215
|
+
|
|
216
|
+
await page.locator('input#g-name').fill('Test Item 2');
|
|
217
|
+
await page.locator('#g-license').selectOption('');
|
|
218
|
+
await page.locator('.g-save-item').click();
|
|
219
|
+
await waitForIdlePage(page);
|
|
220
|
+
|
|
221
|
+
await openItem(page, 'Test Item 2');
|
|
222
|
+
await expect(page.locator('.g-item-license')).toContainText('Unspecified');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test('edit an item that has an unspecified license', async ({ page }) => {
|
|
226
|
+
await login(page, ADMIN.login, ADMIN.password);
|
|
227
|
+
await gotoMyFolders(page);
|
|
228
|
+
await openFolder(page, 'Public');
|
|
229
|
+
await openItem(page, 'Test Item 2');
|
|
230
|
+
|
|
231
|
+
await openEditItemDialog(page);
|
|
232
|
+
// The unspecified license is selected by default.
|
|
233
|
+
await expectLicenseSelect(page.locator('#g-license'), '');
|
|
234
|
+
|
|
235
|
+
await page.locator('#g-license').selectOption(MIT_LICENSE);
|
|
236
|
+
await page.locator('.g-save-item').click();
|
|
237
|
+
await waitForIdlePage(page);
|
|
238
|
+
|
|
239
|
+
await expect(page.locator('.g-item-license')).toContainText(MIT_LICENSE);
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('edit an item to have an unspecified license', async ({ page }) => {
|
|
243
|
+
await login(page, ADMIN.login, ADMIN.password);
|
|
244
|
+
await gotoMyFolders(page);
|
|
245
|
+
await openFolder(page, 'Public');
|
|
246
|
+
await openItem(page, 'Test Item 2');
|
|
247
|
+
|
|
248
|
+
await openEditItemDialog(page);
|
|
249
|
+
await expectLicenseSelect(page.locator('#g-license'), MIT_LICENSE);
|
|
250
|
+
|
|
251
|
+
await page.locator('#g-license').selectOption('');
|
|
252
|
+
await page.locator('.g-save-item').click();
|
|
253
|
+
await waitForIdlePage(page);
|
|
254
|
+
|
|
255
|
+
await expect(page.locator('.g-item-license')).toContainText('Unspecified');
|
|
256
|
+
});
|
|
257
|
+
});
|