girder 5.0.19.dev20__tar.gz → 5.0.19.dev22__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.
Files changed (261) hide show
  1. {girder-5.0.19.dev20/girder.egg-info → girder-5.0.19.dev22}/PKG-INFO +1 -1
  2. girder-5.0.19.dev22/girder/web/tests/spec/plugin_slicer_cli_web_config_view.spec.ts +57 -0
  3. girder-5.0.19.dev22/girder/web/tests/spec/plugin_slicer_cli_web_container_view.spec.ts +79 -0
  4. girder-5.0.19.dev22/girder/web/tests/spec/plugin_slicer_cli_web_item_selector.spec.ts +159 -0
  5. girder-5.0.19.dev22/girder/web/tests/spec/plugin_slicer_cli_web_panel_group.spec.ts +89 -0
  6. girder-5.0.19.dev22/girder/web/tests/spec/plugin_slicer_cli_web_parser.spec.ts +538 -0
  7. girder-5.0.19.dev22/girder/web/tests/spec/plugin_slicer_cli_web_task.spec.ts +77 -0
  8. girder-5.0.19.dev22/girder/web/tests/spec/plugin_slicer_cli_web_widget_model.spec.ts +384 -0
  9. girder-5.0.19.dev22/girder/web/tests/spec/plugin_slicer_cli_web_widget_view.spec.ts +765 -0
  10. {girder-5.0.19.dev20 → girder-5.0.19.dev22/girder.egg-info}/PKG-INFO +1 -1
  11. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder.egg-info/SOURCES.txt +8 -0
  12. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder.egg-info/scm_file_list.json +9 -0
  13. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder.egg-info/scm_version.json +2 -2
  14. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.circleci/Dockerfile +0 -0
  15. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.circleci/build_plugins.py +0 -0
  16. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.circleci/config.yml +0 -0
  17. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.circleci/generatePyEnvChecksum.sh +0 -0
  18. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.circleci/publish_npm.sh +0 -0
  19. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.circleci/publish_pypi.sh +0 -0
  20. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.circleci/rabbitmq.conf +0 -0
  21. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.codecov.yml +0 -0
  22. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.dockerignore +0 -0
  23. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.editorconfig +0 -0
  24. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.git-blame-ignore-revs +0 -0
  25. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.github/workflows/codespell.yml +0 -0
  26. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.gitignore +0 -0
  27. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.pre-commit-config.yaml +0 -0
  28. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/.readthedocs.yml +0 -0
  29. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/CHANGELOG.rst +0 -0
  30. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/CMakeLists.txt +0 -0
  31. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/CONTRIBUTING.rst +0 -0
  32. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/Dockerfile +0 -0
  33. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/LICENSE +0 -0
  34. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/MANIFEST.in +0 -0
  35. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/README.rst +0 -0
  36. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/clients/python/README.rst +0 -0
  37. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/clients/python/girder_client/__init__.py +0 -0
  38. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/clients/python/girder_client/_jsonemitter.py +0 -0
  39. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/clients/python/girder_client/cli.py +0 -0
  40. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/clients/python/pyproject.toml +0 -0
  41. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/clients/python/setup.py +0 -0
  42. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docker-compose.yml +0 -0
  43. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/admin-docs.rst +0 -0
  44. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/api-docs.rst +0 -0
  45. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/build-docs.rst +0 -0
  46. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/conf.py +0 -0
  47. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/configuration.rst +0 -0
  48. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/dependencies.rst +0 -0
  49. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/deployment.rst +0 -0
  50. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/dev-installation.rst +0 -0
  51. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/developer-cookbook.rst +0 -0
  52. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/developer-docs.rst +0 -0
  53. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/development.rst +0 -0
  54. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/favicon.ico +0 -0
  55. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/images/dicom-viewer.png +0 -0
  56. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/index.rst +0 -0
  57. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/license.png +0 -0
  58. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/list_env_settings.py +0 -0
  59. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/list_env_settings.yaml +0 -0
  60. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/migration-guide.rst +0 -0
  61. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/mount.rst +0 -0
  62. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/plugin-development.rst +0 -0
  63. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/plugins.rst +0 -0
  64. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/python-client.rst +0 -0
  65. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/requirements-docs.txt +0 -0
  66. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/security.rst +0 -0
  67. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/sftp.rst +0 -0
  68. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/static/custom.css +0 -0
  69. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/user-docs.rst +0 -0
  70. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/docs/user-guide.rst +0 -0
  71. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/__init__.py +0 -0
  72. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/__init__.py +0 -0
  73. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/access.py +0 -0
  74. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/api_docs.mako +0 -0
  75. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/api_main.py +0 -0
  76. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/describe.py +0 -0
  77. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/docs.py +0 -0
  78. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/filter_logging.py +0 -0
  79. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/rest.py +0 -0
  80. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/sftp.py +0 -0
  81. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/__init__.py +0 -0
  82. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/api_key.py +0 -0
  83. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/assetstore.py +0 -0
  84. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/collection.py +0 -0
  85. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/file.py +0 -0
  86. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/folder.py +0 -0
  87. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/group.py +0 -0
  88. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/item.py +0 -0
  89. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/resource.py +0 -0
  90. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/system.py +0 -0
  91. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/token.py +0 -0
  92. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/api/v1/user.py +0 -0
  93. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/asgi.py +0 -0
  94. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/cli/__init__.py +0 -0
  95. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/cli/mount.py +0 -0
  96. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/cli/serve.py +0 -0
  97. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/cli/sftpd.py +0 -0
  98. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/cli/shell.py +0 -0
  99. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/constants.py +0 -0
  100. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/events.py +0 -0
  101. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/exceptions.py +0 -0
  102. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/mail_templates/_footer.mako +0 -0
  103. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/mail_templates/_header.mako +0 -0
  104. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/mail_templates/accountApproval.mako +0 -0
  105. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/mail_templates/accountApproved.mako +0 -0
  106. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/mail_templates/emailVerification.mako +0 -0
  107. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/mail_templates/groupInvite.mako +0 -0
  108. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/mail_templates/temporaryAccess.mako +0 -0
  109. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/__init__.py +0 -0
  110. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/api_key.py +0 -0
  111. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/assetstore.py +0 -0
  112. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/collection.py +0 -0
  113. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/file.py +0 -0
  114. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/folder.py +0 -0
  115. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/group.py +0 -0
  116. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/item.py +0 -0
  117. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/model_base.py +0 -0
  118. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/setting.py +0 -0
  119. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/token.py +0 -0
  120. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/upload.py +0 -0
  121. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/models/user.py +0 -0
  122. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/notification.py +0 -0
  123. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/plugin.py +0 -0
  124. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/settings.py +0 -0
  125. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/tasks.py +0 -0
  126. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/__init__.py +0 -0
  127. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/_cache.py +0 -0
  128. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/_hash_state.py +0 -0
  129. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/abstract_assetstore_adapter.py +0 -0
  130. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/acl_mixin.py +0 -0
  131. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/assetstore_utilities.py +0 -0
  132. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/config.py +0 -0
  133. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/error.mako +0 -0
  134. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/filesystem_assetstore_adapter.py +0 -0
  135. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/mail_utils.py +0 -0
  136. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/model_importer.py +0 -0
  137. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/path.py +0 -0
  138. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/progress.py +0 -0
  139. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/s3_assetstore_adapter.py +0 -0
  140. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/search.py +0 -0
  141. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/server.py +0 -0
  142. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/setting_utilities.py +0 -0
  143. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/system.py +0 -0
  144. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/webroot.py +0 -0
  145. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/utility/ziputil.py +0 -0
  146. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/.env.development +0 -0
  147. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/.gitignore +0 -0
  148. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/.prettierrc.json +0 -0
  149. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/README.rst +0 -0
  150. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/Girder_Favicon.png +0 -0
  151. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/Girder_Mark.png +0 -0
  152. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/fontello-BGLM866c.svg +0 -0
  153. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/fontello-CMxI46LA.eot +0 -0
  154. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/fontello-Ddaw8Z2O.woff2 +0 -0
  155. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/fontello-KuItqCW9.ttf +0 -0
  156. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/fontello-_lT35XxX.woff +0 -0
  157. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/glyphicons-halflings-regular-BKjkU69z.woff +0 -0
  158. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/glyphicons-halflings-regular-BUJKDMgK.eot +0 -0
  159. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/glyphicons-halflings-regular-CSehLiBc.svg +0 -0
  160. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/glyphicons-halflings-regular-DrwTMapi.ttf +0 -0
  161. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/glyphicons-halflings-regular-DzqM6ju8.woff2 +0 -0
  162. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/index-1kh0UpCT.css +0 -0
  163. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/index-DH5Or_NP.js +0 -0
  164. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/index-DH5Or_NP.js.map +0 -0
  165. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/jsoneditor-icons-CIlYC0TY.svg +0 -0
  166. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-300-B6tDWRxp.woff2 +0 -0
  167. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-300-DZbNTRe6.woff +0 -0
  168. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-300italic-DLsXqxhU.woff2 +0 -0
  169. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-300italic-Dfz31Up5.woff +0 -0
  170. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-400-D5zbb_EN.woff +0 -0
  171. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-400-DLgeRt71.woff2 +0 -0
  172. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-400italic-DpGQ6Ktj.woff2 +0 -0
  173. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-400italic-UJbezL8h.woff +0 -0
  174. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-600-CCvT4JHQ.woff2 +0 -0
  175. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-600-DHWfDY-G.woff +0 -0
  176. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-600italic-X8kCjSq_.woff +0 -0
  177. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-600italic-slqXzGub.woff2 +0 -0
  178. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-700-CsbQbrjx.woff2 +0 -0
  179. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-700-DNl7WOH5.woff +0 -0
  180. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-700italic-BtE7VvhE.woff2 +0 -0
  181. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-700italic-hc2P_kZo.woff +0 -0
  182. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-800-CbJOM4_m.woff2 +0 -0
  183. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-800-XaYTAPrv.woff +0 -0
  184. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-800italic-DqvYew-K.woff +0 -0
  185. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/assets/open-sans-latin-800italic-JIGkTxpX.woff2 +0 -0
  186. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/index.html +0 -0
  187. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/auth.js +0 -0
  188. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/constants.js +0 -0
  189. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/dialog.js +0 -0
  190. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/events.js +0 -0
  191. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/index.ts +0 -0
  192. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/main.ts +0 -0
  193. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/misc.js +0 -0
  194. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/pluginUtils.js +0 -0
  195. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/rest.js +0 -0
  196. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/router.js +0 -0
  197. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/routes.js +0 -0
  198. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/version.js +0 -0
  199. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/dist/src/src/vite-env.d.ts +0 -0
  200. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/env.d.ts +0 -0
  201. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/playwright.config.ts +0 -0
  202. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/coverage.ts +0 -0
  203. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/playwright-setup.ts +0 -0
  204. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/playwright-teardown.ts +0 -0
  205. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/server.ts +0 -0
  206. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/admin.spec.ts +0 -0
  207. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/browser.spec.ts +0 -0
  208. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/collection.spec.ts +0 -0
  209. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/collectionBaseClass.spec.ts +0 -0
  210. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/customWidgets.spec.ts +0 -0
  211. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/data/README.md +0 -0
  212. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/data/nomime.dat +0 -0
  213. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/data/slicer_cli_web_multiple_test.xml +0 -0
  214. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/data/slicer_cli_web_test.xml +0 -0
  215. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/data/ten_byte_file.txt +0 -0
  216. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/file_upload.spec.ts +0 -0
  217. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_authorized_upload.spec.ts +0 -0
  218. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_hashsum_download.spec.ts +0 -0
  219. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_homepage.spec.ts +0 -0
  220. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_item_licenses.spec.ts +0 -0
  221. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_readme.spec.ts +0 -0
  222. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_slicer_cli_web.spec.ts +0 -0
  223. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_terms.spec.ts +0 -0
  224. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_thumbnails.spec.ts +0 -0
  225. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/plugin_user_quota.spec.ts +0 -0
  226. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/spec/setting_show_download.spec.ts +0 -0
  227. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/web/tests/util.ts +0 -0
  228. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/worker_plugin.py +0 -0
  229. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder/wsgi.py +0 -0
  230. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder.egg-info/dependency_links.txt +0 -0
  231. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder.egg-info/entry_points.txt +0 -0
  232. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder.egg-info/not-zip-safe +0 -0
  233. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder.egg-info/requires.txt +0 -0
  234. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/girder.egg-info/top_level.txt +0 -0
  235. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/jsdoc.json +0 -0
  236. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/package-lock.json +0 -0
  237. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/package.json +0 -0
  238. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pyproject.toml +0 -0
  239. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/LICENSE +0 -0
  240. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/MANIFEST.in +0 -0
  241. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/pyproject.toml +0 -0
  242. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/pytest_girder/__init__.py +0 -0
  243. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/pytest_girder/assertions.py +0 -0
  244. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/pytest_girder/fixtures.py +0 -0
  245. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/pytest_girder/plugin.py +0 -0
  246. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/pytest_girder/plugin_registry.py +0 -0
  247. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/pytest_girder/utils.py +0 -0
  248. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/pytest_girder/web_client.py +0 -0
  249. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/pytest_girder/setup.py +0 -0
  250. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/requirements-dev.txt +0 -0
  251. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/scripts/midas/README.rst +0 -0
  252. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/scripts/midas/migrate.py +0 -0
  253. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/scripts/midas/requirements.txt +0 -0
  254. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/scripts/midas/walk_girder.py +0 -0
  255. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/scripts/midas/walk_midas.py +0 -0
  256. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/scripts/publicNames.py +0 -0
  257. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/scripts/publicNames.txt +0 -0
  258. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/scripts/test_names.sh +0 -0
  259. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/setup.cfg +0 -0
  260. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/setup.py +0 -0
  261. {girder-5.0.19.dev20 → girder-5.0.19.dev22}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: girder
3
- Version: 5.0.19.dev20
3
+ Version: 5.0.19.dev22
4
4
  Summary: Web-based data management platform
5
5
  Home-page: https://girder.readthedocs.org
6
6
  Author: Kitware, Inc.
@@ -0,0 +1,57 @@
1
+ import { expect, Page, test } from '@playwright/test';
2
+
3
+ import { setupServer } from '../server';
4
+ import { createUser, waitForIdlePage } from '../util';
5
+
6
+ async function asyncRestRequest(page: Page, opts: any) {
7
+ return await page.evaluate((opts) => {
8
+ return new Promise((resolve, reject) => {
9
+ window.girder.rest.restRequest(opts).done((resp: any) => {
10
+ resolve(resp);
11
+ }).fail((resp: any) => {
12
+ reject(resp);
13
+ });
14
+ });
15
+ }, opts);
16
+ }
17
+
18
+ test.describe('Slicer CLI web config view', () => {
19
+ setupServer();
20
+
21
+ test('change the slicer_cli_web task folder setting', async ({ page }) => {
22
+ await createUser(page, 'admin');
23
+ await waitForIdlePage(page);
24
+
25
+ const me = await asyncRestRequest(page, { url: '/user/me' }) as any;
26
+ const folder = await asyncRestRequest(page, {
27
+ url: '/folder',
28
+ method: 'POST',
29
+ data: { name: 'Task Folder', parentType: 'user', parentId: me._id },
30
+ }) as any;
31
+ await waitForIdlePage(page);
32
+
33
+ // Navigate to the plugin's admin settings page.
34
+ await page.getByRole('link', { name: ' Admin console' }).click();
35
+ await page.getByRole('link', { name: ' Plugins' }).click();
36
+ const configLink = page.locator('.g-plugin-config-link[g-route="plugins/slicer_cli_web/config"]');
37
+ await expect(configLink).toBeVisible();
38
+ await configLink.click();
39
+
40
+ await expect(page.locator('#g-slicer-cli-web-form input#g-slicer-cli-web-upload-folder')).toBeVisible();
41
+
42
+ // Fill in the created folder and save.
43
+ await page.locator('#g-slicer-cli-web-upload-folder').fill(folder._id);
44
+ await expect(page.locator('#g-slicer-cli-web-upload-folder')).toHaveValue(folder._id);
45
+
46
+ // Save the settings.
47
+ await page.locator('#g-slicer-cli-web-form input.btn-primary').click();
48
+ await waitForIdlePage(page);
49
+
50
+ const settings = await asyncRestRequest(page, {
51
+ url: '/system/setting',
52
+ method: 'GET',
53
+ data: { list: JSON.stringify(['slicer_cli_web.task_folder']) },
54
+ }) as any;
55
+ expect(settings['slicer_cli_web.task_folder']).toBe(folder._id);
56
+ });
57
+ });
@@ -0,0 +1,79 @@
1
+ import { expect, Page, test } from '@playwright/test';
2
+
3
+ import { setupServer } from '../server';
4
+ import { createUser, logout, waitForIdlePage } from '../util';
5
+
6
+ async function asyncRestRequest(page: Page, opts: any) {
7
+ return await page.evaluate((opts) => {
8
+ return new Promise((resolve, reject) => {
9
+ window.girder.rest.restRequest(opts).done((resp: any) => {
10
+ resolve(resp);
11
+ }).fail((resp: any) => {
12
+ reject(resp);
13
+ });
14
+ });
15
+ }, opts);
16
+ }
17
+
18
+ async function createDefaultTaskFolder(page: Page) {
19
+ const collection = await asyncRestRequest(page, {
20
+ url: '/collection',
21
+ method: 'POST',
22
+ data: { name: 'Tasks', description: 'Default Tasks', public: true },
23
+ }) as any;
24
+ const folder = await asyncRestRequest(page, {
25
+ url: '/folder',
26
+ method: 'POST',
27
+ data: {
28
+ name: 'Slicer CLI Web Tasks',
29
+ parentType: 'collection',
30
+ parentId: collection._id,
31
+ public: true,
32
+ },
33
+ }) as any;
34
+ await asyncRestRequest(page, {
35
+ url: '/system/setting',
36
+ method: 'PUT',
37
+ data: { key: 'slicer_cli_web.task_folder', value: folder._id },
38
+ });
39
+ }
40
+
41
+ async function navigateToCollectionsFolder(page: Page, collectionName: string, folderName: string) {
42
+ await page.locator('a.g-nav-link[g-target="collections"]').click();
43
+ await expect(page.locator('.g-collection-list-entry').first()).toBeVisible({ timeout: 10000 });
44
+ await page.locator('.g-collection-link', { hasText: collectionName }).first().click();
45
+ await expect(page.locator('.g-folder-list-link').first()).toBeVisible({ timeout: 10000 });
46
+ await page.locator('.g-folder-list-link', { hasText: folderName }).first().click();
47
+ await expect(page.locator('.g-hierarchy-widget').first()).toBeVisible({ timeout: 10000 });
48
+ }
49
+
50
+ test.describe('Slicer CLI web upload docker images button', () => {
51
+ setupServer();
52
+
53
+ test('the upload CLI task button is visible only for the admin-configured task folder', async ({ page }) => {
54
+ await createUser(page, 'admin');
55
+ await waitForIdlePage(page);
56
+ await createDefaultTaskFolder(page);
57
+ await waitForIdlePage(page);
58
+
59
+ await navigateToCollectionsFolder(page, 'Tasks', 'Slicer CLI Web Tasks');
60
+
61
+ // The button is visible for an admin in the configured task folder.
62
+ const uploadButton = page.locator('.g-upload-slicer-cli-task-button');
63
+ await expect(uploadButton).toBeVisible();
64
+
65
+ // Clicking it opens the upload image dialog.
66
+ await uploadButton.click();
67
+ await expect(page.locator('#g-slicer-cli-web-image')).toBeVisible();
68
+ await page.locator('#g-slicer-cli-web-upload-form button.close').click();
69
+ await expect(page.locator('#g-slicer-cli-web-image')).toBeHidden();
70
+
71
+ // A normal user never sees the button.
72
+ await logout(page);
73
+ await createUser(page, 'johndoe', 'john.doe@girder.test', 'John', 'Doe', 'password!');
74
+ await waitForIdlePage(page);
75
+
76
+ await navigateToCollectionsFolder(page, 'Tasks', 'Slicer CLI Web Tasks');
77
+ await expect(page.locator('.g-upload-slicer-cli-task-button')).toHaveCount(0);
78
+ });
79
+ });
@@ -0,0 +1,159 @@
1
+ import { expect, Page, test } from '@playwright/test';
2
+
3
+ import { setupServer } from '../server';
4
+ import { createUser, waitForIdlePage } from '../util';
5
+
6
+ async function asyncRestRequest(page: Page, opts: any) {
7
+ return await page.evaluate((opts) => {
8
+ return new Promise((resolve, reject) => {
9
+ window.girder.rest.restRequest(opts).done((resp: any) => {
10
+ resolve(resp);
11
+ }).fail((resp: any) => {
12
+ reject(resp);
13
+ });
14
+ });
15
+ }, opts);
16
+ }
17
+
18
+ async function selectedNames(page: Page) {
19
+ return page.evaluate(() => {
20
+ const girder = (window as any).girder;
21
+ const $ = girder.$;
22
+ const names: string[] = [];
23
+ $('.g-selected .g-item-list-link').each((index: number, el: any) => {
24
+ names.push($(el).clone().children().remove().end().text());
25
+ });
26
+ return names;
27
+ });
28
+ }
29
+
30
+ test.describe('Slicer CLI web item selector regex selection', () => {
31
+ setupServer();
32
+
33
+ test('browser hierarchy paginated selection', async ({ page }) => {
34
+ await createUser(page, 'admin');
35
+ await waitForIdlePage(page);
36
+
37
+ // Seed a folder hierarchy with many items through REST.
38
+ const me = await asyncRestRequest(page, { url: '/user/me' }) as any;
39
+ const folder = await asyncRestRequest(page, {
40
+ url: '/folder',
41
+ method: 'POST',
42
+ data: { name: 'top level folder', parentType: 'user', parentId: me._id },
43
+ }) as any;
44
+ await asyncRestRequest(page, {
45
+ url: '/folder',
46
+ method: 'POST',
47
+ data: { name: 'subfolder', parentType: 'folder', parentId: folder._id },
48
+ });
49
+ const item = await asyncRestRequest(page, {
50
+ url: '/item',
51
+ method: 'POST',
52
+ data: { name: 'an item', folderId: folder._id },
53
+ }) as any;
54
+ for (let i = 0; i < 20; i += 1) {
55
+ await asyncRestRequest(page, {
56
+ url: '/item',
57
+ method: 'POST',
58
+ data: { name: `item#: ${i}`, folderId: folder._id },
59
+ });
60
+ }
61
+ await waitForIdlePage(page);
62
+
63
+ // Instantiate the multi-file selector directly against the seeded folder.
64
+ await page.evaluate(async ({ folderId, itemId }) => {
65
+ const girder = (window as any).girder;
66
+ const slicer = girder.plugins.slicer_cli_web;
67
+ const folderModel = new girder.models.FolderModel({ _id: folderId });
68
+ await new Promise((resolve, reject) => {
69
+ folderModel.once('g:fetched', resolve).once('g:error', reject).fetch();
70
+ });
71
+ const itemModel = new girder.models.ItemModel({ _id: itemId });
72
+ const dialogEl = girder.$('<div/>').appendTo('body');
73
+ const selector = new slicer.views.ItemSelectorWidget({
74
+ parentView: { registerChildView: () => undefined },
75
+ el: dialogEl.get(0),
76
+ rootPath: folderModel,
77
+ root: folderModel,
78
+ defaultSelectedResource: itemModel,
79
+ selectItem: true,
80
+ showItems: true,
81
+ model: new slicer.models.WidgetModel({
82
+ type: 'multi',
83
+ title: 'Title',
84
+ id: 'item-widget',
85
+ }),
86
+ });
87
+ selector.once('g:saved', () => {
88
+ selector.$el.modal('hide');
89
+ });
90
+ (window as any).__itemSelector = selector;
91
+ selector.render();
92
+ }, { folderId: folder._id, itemId: item._id });
93
+
94
+ await expect(page.locator('.g-item-list-entry')).toHaveCount(21);
95
+
96
+ const input = page.locator('#g-input-element');
97
+
98
+ await input.fill('[0-9][1-3]');
99
+ await expect(page.locator('.g-selected .g-item-list-link')).not.toHaveCount(0);
100
+ let names = await selectedNames(page);
101
+ expect(names).not.toContain('item#: 10');
102
+ expect(names).toContain('item#: 11');
103
+ expect(names).toContain('item#: 12');
104
+ expect(names).toContain('item#: 13');
105
+ expect(names).not.toContain('item#: 14');
106
+
107
+ await input.fill(' [4-7]$');
108
+ await expect(page.locator('.g-selected .g-item-list-link')).not.toHaveCount(0);
109
+ names = await selectedNames(page);
110
+ expect(names).toContain('item#: 4');
111
+ expect(names).toContain('item#: 5');
112
+ expect(names).toContain('item#: 6');
113
+ expect(names).toContain('item#: 7');
114
+ expect(names).not.toContain('item#: 14');
115
+ expect(names).not.toContain('item#: 17');
116
+
117
+ await input.fill('');
118
+ await expect(page.locator('.g-selected .g-item-list-link')).toHaveCount(21);
119
+
120
+ await input.fill('\\');
121
+ await expect(page.locator('.g-selected .g-item-list-link')).toHaveCount(0);
122
+ await expect(page.locator('.g-validation-failed-message:visible')).toHaveCount(1);
123
+
124
+ await page.evaluate(() => (window as any).__itemSelector.$('.g-submit-button').click());
125
+ await expect(page.locator('.g-validation-failed-message:visible')).toHaveCount(1);
126
+
127
+ // Resetting the selector re-highlights every item.
128
+ await page.evaluate(() => {
129
+ const selector = (window as any).__itemSelector;
130
+ selector.$('#g-input-element').val('');
131
+ selector._selectModel();
132
+ selector._hierarchyView.itemListView.trigger('g:changed');
133
+ });
134
+ await expect(page.locator('.g-selected .g-item-list-link')).toHaveCount(21);
135
+
136
+ await input.fill('[5]$');
137
+ await expect(page.locator('.g-selected .g-item-list-link')).not.toHaveCount(0);
138
+ names = await selectedNames(page);
139
+ expect(names).toContain('item#: 5');
140
+ expect(names).toContain('item#: 15');
141
+
142
+ await page.evaluate(() => (window as any).__itemSelector.$('.g-submit-button').click());
143
+ await expect.poll(() => page.evaluate(() => {
144
+ const model = (window as any).__itemSelector.model;
145
+ const value = model.get('value');
146
+ return value ? value.get('name') : null;
147
+ }), { timeout: 8000 }).toBe('[5]$');
148
+
149
+ const state = await page.evaluate(() => {
150
+ const model = (window as any).__itemSelector.model;
151
+ return {
152
+ path: model.get('path'),
153
+ folderName: model.get('folderName'),
154
+ };
155
+ });
156
+ expect(state.path.filter(Boolean)).toEqual(['top level folder']);
157
+ expect(state.folderName).toBe('top level folder');
158
+ });
159
+ });
@@ -0,0 +1,89 @@
1
+ import { expect, test } from '@playwright/test';
2
+
3
+ import { setupServer } from '../server';
4
+
5
+ const SPEC_XML = '' +
6
+ '<?xml version="1.0" encoding="UTF-8" ?>' +
7
+ '<executable>' +
8
+ ' <category>Example</category>' +
9
+ ' <title>Simple Example</title>' +
10
+ ' <description>Report on a few input parameters.</description>' +
11
+ ' <version>0.1.0</version>' +
12
+ ' <license>Apache 2.0</license>' +
13
+ ' <contributor>David Manthey (Kitware)</contributor>' +
14
+ ' <parameters>' +
15
+ ' <label>IO</label>' +
16
+ ' <description>Input/output parameters.</description>' +
17
+ ' <image>' +
18
+ ' <name>ImageFile</name>' +
19
+ ' <label>Input Image</label>' +
20
+ ' <channel>input</channel>' +
21
+ ' <description>Input image</description>' +
22
+ ' <index>0</index>' +
23
+ ' </image>' +
24
+ ' <double-vector>' +
25
+ ' <name>Color1</name>' +
26
+ ' <label>RGB Color</label>' +
27
+ ' <description>An RGB Color Vector</description>' +
28
+ ' <channel>input</channel>' +
29
+ ' <index>1</index>' +
30
+ ' </double-vector>' +
31
+ ' <double-vector>' +
32
+ ' <name>Color2</name>' +
33
+ ' <label>YCbCr Color</label>' +
34
+ ' <description>A YCBCr Color Vector</description>' +
35
+ ' <channel>input</channel>' +
36
+ ' <index>2</index>' +
37
+ ' </double-vector>' +
38
+ ' </parameters>' +
39
+ '</executable>';
40
+
41
+ test.describe('Slicer CLI web panel group', () => {
42
+ setupServer();
43
+
44
+ test('panel group', async ({ page }) => {
45
+ const fails = await page.evaluate(async (xml) => {
46
+ const w = window as any;
47
+ const girder = w.girder;
48
+ const slicer = girder.plugins.slicer_cli_web;
49
+ const parentView = { registerChildView: () => undefined };
50
+ const el = girder.$('<div/>').appendTo('body');
51
+
52
+ const failures: string[] = [];
53
+ const is = (actual: any, expected: any, msg: string) => {
54
+ if (actual !== expected) {
55
+ failures.push(`${msg}: expected ${JSON.stringify(expected)} got ${JSON.stringify(actual)}`);
56
+ }
57
+ };
58
+ const waitFor = (cond: () => boolean, timeout = 5000) => new Promise<void>((resolve, reject) => {
59
+ const start = Date.now();
60
+ const tick = () => {
61
+ if (cond()) {
62
+ resolve();
63
+ return;
64
+ }
65
+ if (Date.now() - start > timeout) {
66
+ reject(new Error('waitFor timeout'));
67
+ return;
68
+ }
69
+ setTimeout(tick, 20);
70
+ };
71
+ tick();
72
+ });
73
+
74
+ const view = new slicer.views.PanelGroup({
75
+ closeButton: true,
76
+ parentView,
77
+ el: el.get(0),
78
+ });
79
+ view.render();
80
+ is(view.$el.hasClass('hidden'), true, 'hidden initially');
81
+
82
+ view.setAnalysis('/test', xml);
83
+ await waitFor(() => view.panels.length > 0);
84
+ is(view.panels.length, 1, 'panel count');
85
+ return failures;
86
+ }, SPEC_XML);
87
+ expect(fails).toEqual([]);
88
+ });
89
+ });