diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 848e3fa76..17c3bf460 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -143,7 +143,7 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Cypress screenshots
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v3
if: failure()
with:
name: cypress-screenshots
diff --git a/package-lock.json b/package-lock.json
index 6af6ac5b3..6e6758dc4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -34923,6 +34923,7 @@
"integrity": "sha512-qokTiqxD6GjODy5ETAIgzsRgnBWWQHQH2ghy86PU7mIn/wuWeTwF3otyNQZxWBwVn8XNr8Tdzj/QfUXpH+gRZA==",
"dev": true,
"hasInstallScript": true,
+ "license": "MIT",
"dependencies": {
"cross-spawn": "^5.0.1",
"spawn-sync": "^1.0.15",
@@ -34934,6 +34935,7 @@
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"lru-cache": "^4.0.1",
"shebang-command": "^1.2.0",
@@ -34945,6 +34947,7 @@
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
@@ -34955,6 +34958,7 @@
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"shebang-regex": "^1.0.0"
},
@@ -34967,6 +34971,7 @@
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -34976,6 +34981,7 @@
"resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz",
"integrity": "sha512-16uPglFkRPzgiUXYMi1Jf8Z5EzN1iB4V0ZtMXcHZnwsBtQhhHeCqoWw7tsUY42hJGNDWtUsVLTjakIa5BgAxCw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
@@ -34987,7 +34993,8 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/prelude-ls": {
"version": "1.2.1",
@@ -35283,7 +35290,8 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/psl": {
"version": "1.9.0",
@@ -38192,6 +38200,7 @@
"integrity": "sha512-9DWBgrgYZzNghseho0JOuh+5fg9u6QWhAWa51QC7+U5rCheZ/j1DrEZnyE0RBBRqZ9uEXGPgSSM0nky6burpVw==",
"dev": true,
"hasInstallScript": true,
+ "license": "MIT",
"dependencies": {
"concat-stream": "^1.4.7",
"os-shim": "^0.1.2"
@@ -38205,6 +38214,7 @@
"engines": [
"node >= 0.8"
],
+ "license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
@@ -38216,13 +38226,15 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/spawn-sync/node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
@@ -38237,13 +38249,15 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/spawn-sync/node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"safe-buffer": "~5.1.0"
}
diff --git a/package.json b/package.json
index 446462aaa..6549c4e3f 100644
--- a/package.json
+++ b/package.json
@@ -23,12 +23,14 @@
"@types/node": "16.18.12",
"@types/react": "18.0.27",
"@types/react-dom": "18.0.10",
+ "async-mutex": "0.5.0",
"bootstrap": "5.2.3",
"classnames": "2.5.1",
"html-react-parser": "3.0.16",
"i18next": "22.4.9",
"i18next-browser-languagedetector": "7.0.1",
"i18next-http-backend": "2.1.1",
+ "js-md5": "0.8.3",
"lodash": "^4.17.21",
"moment-timezone": "0.5.43",
"react-bootstrap": "2.7.2",
@@ -44,9 +46,7 @@
"typescript": "4.9.5",
"use-deep-compare": "1.2.1",
"vite-plugin-istanbul": "4.0.1",
- "web-vitals": "2.1.4",
- "js-md5": "0.8.3",
- "async-mutex": "0.5.0"
+ "web-vitals": "2.1.4"
},
"scripts": {
"start": "vite --base=/spa",
diff --git a/src/sections/create-dataset/CreateDataset.tsx b/src/sections/create-dataset/CreateDataset.tsx
index ee7e3690b..a7862eb83 100644
--- a/src/sections/create-dataset/CreateDataset.tsx
+++ b/src/sections/create-dataset/CreateDataset.tsx
@@ -13,6 +13,11 @@ import { CollectionRepository } from '../../collection/domain/repositories/Colle
import { useLoading } from '../loading/LoadingContext'
import { ROOT_COLLECTION_ALIAS } from '../../collection/domain/models/Collection'
+import { BreadcrumbsGenerator } from '../shared/hierarchy/BreadcrumbsGenerator'
+import { useCollection } from '../collection/useCollection'
+import { PageNotFound } from '../page-not-found/PageNotFound'
+import { CreateDatasetSkeleton } from './CreateDatasetSkeleton'
+
interface CreateDatasetProps {
datasetRepository: DatasetRepository
metadataBlockInfoRepository: MetadataBlockInfoRepository
@@ -30,6 +35,11 @@ export function CreateDataset({
const { isModalOpen, hideModal } = useNotImplementedModal()
const { setIsLoading } = useLoading()
+ const { collection, isLoading: isLoadingCollection } = useCollection(
+ collectionRepository,
+ collectionId
+ )
+
const { collectionUserPermissions, isLoading: isLoadingCollectionUserPermissions } =
useGetCollectionUserPermissions({
collectionIdOrAlias: collectionId,
@@ -37,10 +47,19 @@ export function CreateDataset({
})
const canUserAddDataset = Boolean(collectionUserPermissions?.canAddDataset)
+ const isLoadingData = isLoadingCollectionUserPermissions || isLoadingCollection
useEffect(() => {
- setIsLoading(isLoadingCollectionUserPermissions)
- }, [isLoadingCollectionUserPermissions, setIsLoading])
+ setIsLoading(isLoadingData)
+ }, [isLoadingData, setIsLoading])
+
+ if (!isLoadingCollection && !collection) {
+ return
+ }
+
+ if (isLoadingCollection || !collection) {
+ return
+ }
if (collectionUserPermissions && !canUserAddDataset) {
return (
@@ -56,6 +75,11 @@ export function CreateDataset({
<>
+
diff --git a/src/sections/create-dataset/CreateDatasetSkeleton.tsx b/src/sections/create-dataset/CreateDatasetSkeleton.tsx
new file mode 100644
index 000000000..c885f614f
--- /dev/null
+++ b/src/sections/create-dataset/CreateDatasetSkeleton.tsx
@@ -0,0 +1,35 @@
+import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'
+import { Col, Row } from '@iqss/dataverse-design-system'
+import { BreadcrumbsSkeleton } from '../shared/hierarchy/BreadcrumbsSkeleton'
+import 'react-loading-skeleton/dist/skeleton.css'
+import { SeparationLine } from '../shared/layout/SeparationLine/SeparationLine'
+import { MetadataFormSkeleton } from '../shared/form/DatasetMetadataForm/MetadataForm/MetadataFormSkeleton'
+
+export const CreateDatasetSkeleton = () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+)
diff --git a/tests/component/sections/create-dataset/CreateDataset.spec.tsx b/tests/component/sections/create-dataset/CreateDataset.spec.tsx
index 8b803aff4..4d882a954 100644
--- a/tests/component/sections/create-dataset/CreateDataset.spec.tsx
+++ b/tests/component/sections/create-dataset/CreateDataset.spec.tsx
@@ -15,6 +15,9 @@ const userPermissionsMock = CollectionMother.createUserPermissions()
const collectionMetadataBlocksInfo =
MetadataBlockInfoMother.getByCollectionIdDisplayedOnCreateTrue()
+const COLLECTION_NAME = 'Collection Name'
+const collection = CollectionMother.create({ name: COLLECTION_NAME })
+
describe('Create Dataset', () => {
beforeEach(() => {
datasetRepository.create = cy.stub().resolves({ persistentId: 'persistentId' })
@@ -23,6 +26,47 @@ describe('Create Dataset', () => {
.resolves(collectionMetadataBlocksInfo)
collectionRepository.getUserPermissions = cy.stub().resolves(userPermissionsMock)
+ collectionRepository.getById = cy.stub().resolves(collection)
+ })
+
+ it('should show page not found when owner collection does not exist', () => {
+ collectionRepository.getById = cy.stub().resolves(null)
+ cy.customMount(
+
+ )
+ cy.findByText('Page Not Found').should('exist')
+ })
+
+ it('should show loading skeleton while loading the collection', () => {
+ cy.customMount(
+
+ )
+ cy.findByTestId('create-dataset-skeleton').should('exist')
+ })
+
+ it('should render the correct breadcrumbs', () => {
+ cy.customMount(
+
+ )
+
+ cy.findByRole('link', { name: 'Root' }).should('exist')
+
+ cy.get('li[aria-current="page"]')
+ .should('exist')
+ .should('have.text', 'Create Dataset')
+ .should('have.class', 'active')
})
it('renders the Host Collection Form for root collection', () => {
diff --git a/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts b/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts
index 8ac0dcd21..804d40307 100644
--- a/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts
+++ b/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts
@@ -41,19 +41,16 @@ describe('Collection Page', () => {
addDataBtn.click({ force: true })
cy.findByText('New Dataset').should('be.visible').click({ force: true })
})
- cy.wait(1000)
- cy.findByText(/Create Dataset/i).should('exist')
-
cy.visit('/spa')
- cy.wait(1000)
cy.get('main').within(() => {
const addDataBtn = cy.findByRole('button', { name: /Add Data/i })
addDataBtn.should('exist')
addDataBtn.click({ force: true })
cy.findByText('New Dataset').should('be.visible').click({ force: true })
})
- cy.wait(1000)
- cy.findByText(/Create Dataset/i).should('exist')
+ cy.get(`h1`)
+ .findByText(/Create Dataset/i)
+ .should('exist')
})
it('log out Dataverse Admin user', () => {
@@ -68,8 +65,6 @@ describe('Collection Page', () => {
describe.skip('Currently skipping all tests as we are only rendering an infinite scrollable container. Please refactor these tests if a toggle button is added to switch between pagination and infinite scroll.', () => {
it('navigates to the correct page of the datasets list when passing the page query param', () => {
cy.wrap(DatasetHelper.createMany(12), { timeout: 10000 }).then(() => {
- cy.wait(1500) // Wait for the datasets to be created
-
cy.visit('/spa?page=2')
cy.findAllByText(/Root/i).should('exist')
cy.findByText(/Dataverse Admin/i).should('exist')
@@ -80,8 +75,6 @@ describe('Collection Page', () => {
it('updates the page query param when navigating to another page', () => {
cy.wrap(DatasetHelper.createMany(12), { timeout: 10000 }).then(() => {
- cy.wait(2000) // Wait for the datasets to be created
-
cy.visit('/spa')
cy.findAllByText(/Root/i).should('exist')
@@ -95,26 +88,18 @@ describe('Collection Page', () => {
it('correctly changes the pages when using the back and forward buttons from the browser after using some page number button', () => {
cy.wrap(DatasetHelper.createMany(12), { timeout: 10000 }).then(() => {
- cy.wait(1500) // Wait for the datasets to be created
-
cy.visit('/spa?page=2')
cy.findAllByText(/Root/i).should('exist')
cy.findByText(/Dataverse Admin/i).should('exist')
cy.findByText('11 to 12 of 12 Datasets').should('exist')
- cy.wait(1000)
-
cy.findByRole('button', { name: '1' }).click({ force: true })
cy.findByText('1 to 10 of 12 Datasets').should('exist')
- cy.wait(1000)
-
cy.go('back')
cy.findByText('11 to 12 of 12 Datasets').should('exist')
- cy.wait(1000)
-
cy.go('forward')
cy.findByText('1 to 10 of 12 Datasets').should('exist')
})
@@ -134,7 +119,6 @@ describe('Collection Page', () => {
const collectionId = 'collection-1' + Date.now().toString()
cy.wrap(CollectionHelper.create(collectionId)).then(() => {
cy.wrap(DatasetHelper.createMany(12, collectionId), { timeout: 10_000 }).then(() => {
- cy.wait(2_000) // Wait for the datasets to be created
cy.visit(`/spa/collections/${collectionId}`)
cy.findAllByText(/Scientific Research/i).should('exist')
@@ -145,7 +129,6 @@ describe('Collection Page', () => {
cy.get('[data-testid="scrollable-container"]').scrollTo('bottom', {
ensureScrollable: false
})
- cy.wait(1_500)
cy.findByText('12 of 12 Datasets displayed').should('exist')
})
})