Added tests

This commit is contained in:
Giuseppe Digilio
2019-01-10 19:13:40 +01:00
parent 5723a1df84
commit 9edd18f289
10 changed files with 1516 additions and 47 deletions

View File

@@ -55,7 +55,54 @@ export const mockSectionsErrors = [
} }
]; ];
export const submissionRestResponse = [ export const mockUploadResponse1Errors = {
errors: [
{
message: 'error.validation.required',
paths: [
'/sections/traditionalpageone/dc.title',
'/sections/traditionalpageone/dc.date.issued'
]
}
]
};
export const mockUploadResponse1ParsedErrors: any = {
traditionalpageone: [
{ path: '/sections/traditionalpageone/dc.title', message: 'error.validation.required' },
{ path: '/sections/traditionalpageone/dc.date.issued', message: 'error.validation.required' }
]
};
export const mockUploadResponse2Errors = {
errors: [
{
message: 'error.validation.required',
paths: [
'/sections/traditionalpageone/dc.title',
'/sections/traditionalpageone/dc.date.issued'
]
},
{
message: 'error.upload',
paths: [
'/sections/upload'
]
}
]
};
export const mockUploadResponse2ParsedErrors = {
traditionalpageone: [
{ path: '/sections/traditionalpageone/dc.title', message: 'error.validation.required' },
{ path: '/sections/traditionalpageone/dc.date.issued', message: 'error.validation.required' }
],
upload: [
{ path: '/sections/upload', message: 'error.upload' }
]
};
export const mockSubmissionRestResponse = [
{ {
id: 826, id: 826,
lastModified: '2018-08-03T12:49:45.268+0000', lastModified: '2018-08-03T12:49:45.268+0000',
@@ -257,6 +304,7 @@ export const submissionRestResponse = [
} }
} }
]; ];
export const mockSubmissionObject = { export const mockSubmissionObject = {
collection: { collection: {
handle: '10673/2', handle: '10673/2',
@@ -476,9 +524,9 @@ export const mockSubmissionObject = {
email: 'dspacedemo+submit@gmail.com', email: 'dspacedemo+submit@gmail.com',
requireCertificate: false, requireCertificate: false,
selfRegistered: false, selfRegistered: false,
self: 'https://rest.api/dspace-spring-rest/api/eperson/epersons/99423c27-b642-4bb9-a9cd-6d910e68dca5', self: 'https://rest.api/dspace-spring-rest/api/eperson/epersons/99423c27-b642-5tg6-a9cd-6d910e68dca5',
id: '99423c27-b642-4bb9-a9cd-6d910e68dca5', id: '99423c27-b642-5tg6-a9cd-6d910e68dca5',
uuid: '99423c27-b642-4bb9-a9cd-6d910e68dca5', uuid: '99423c27-b642-5tg6-a9cd-6d910e68dca5',
type: 'eperson', type: 'eperson',
name: 'dspacedemo+submit@gmail.com', name: 'dspacedemo+submit@gmail.com',
metadata: [ metadata: [
@@ -494,7 +542,7 @@ export const mockSubmissionObject = {
} }
], ],
_links: { _links: {
self: 'https://rest.api/dspace-spring-rest/api/eperson/epersons/99423c27-b642-4bb9-a9cd-6d910e68dca5' self: 'https://rest.api/dspace-spring-rest/api/eperson/epersons/99423c27-b642-5tg6-a9cd-6d910e68dca5'
} }
}, },
id: 826, id: 826,
@@ -518,18 +566,276 @@ export const mockSubmissionObject = {
] ]
} }
], ],
self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/269', self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826',
type: 'workspaceitem', type: 'workspaceitem',
_links: { _links: {
collection: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/269/collection', collection: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/collection',
item: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/269/item', item: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/item',
submissionDefinition: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/269/submissionDefinition', submissionDefinition: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/submissionDefinition',
submitter: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/269/submitter', submitter: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/submitter',
self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/269' self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826'
} }
} };
export const mockSubmissionObjectNew = {
collection: {
handle: '10673/2',
license: 'https://rest.api/dspace-spring-rest/api/core/collections/45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb/license',
defaultAccessConditions: {
pageInfo: {
elementsPerPage: 1,
totalElements: 1,
totalPages: 1,
currentPage: 1
},
page: [
{
name: null,
groupUUID: '11cc35e5-a11d-4b64-b5b9-0052a5d15509',
id: 20,
uuid: 'resource-policy-20',
self: 'https://rest.api/dspace-spring-rest/api/authz/resourcePolicies/20',
type: 'resourcePolicy',
_links: {
self: 'https://rest.api/dspace-spring-rest/api/authz/resourcePolicies/20'
}
}
]
},
logo: {
sizeBytes: 7451,
content: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/content',
format: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/format',
bundleName: null,
self: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425',
id: '3f859425-ffbd-4b0e-bf91-bfeb458a7425',
uuid: '3f859425-ffbd-4b0e-bf91-bfeb458a7425',
type: 'bitstream',
name: null,
metadata: [],
_links: {
content: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/content',
format: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425/format',
self: 'https://rest.api/dspace-spring-rest/api/core/bitstreams/3f859425-ffbd-4b0e-bf91-bfeb458a7425'
}
},
self: 'https://rest.api/dspace-spring-rest/api/core/collections/45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb',
id: '45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb',
uuid: '45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb',
type: 'collection',
name: 'Another Collection of Sample Items',
metadata: [
{
key: 'dc.provenance',
language: null,
value: 'This field is for private provenance information. It is only visible to Administrative users and is not displayed in the user interface by default.'
},
{
key: 'dc.rights.license',
language: null,
value: ''
},
{
key: 'dc.description',
language: null,
value: '<p>This is a <em>DSpace Collection</em> which contains sample DSpace Items.</p>\r\n<p><strong>Collections in DSpace may only contain Items.</strong></p>\r\n<p>This particular Collection has its own logo (the <a href=\'http://www.opensource.org/\'>Open Source Initiative</a> logo).</p>\r\n<p>This introductory text is editable by System Administrators, Community Administrators (of a parent Community) or Collection Administrators (of this Collection).</p>'
},
{
key: 'dc.description.abstract',
language: null,
value: 'This collection contains sample items.'
},
{
key: 'dc.description.tableofcontents',
language: null,
value: '<p>This is the <strong>news</strong> section for this Collection. System Administrators, Community Administrators (of a parent Community) or Collection Administrators (of this Collection) can edit this News field.</p>'
},
{
key: 'dc.rights',
language: null,
value: '<p><em>If this collection had a specific copyright statement, it would be placed here.</em></p>'
},
{
key: 'dc.title',
language: null,
value: 'Collection of Sample Items'
}
],
_links: {
license: 'https://rest.api/dspace-spring-rest/api/core/collections/45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb/license',
defaultAccessConditions: 'https://rest.api/dspace-spring-rest/api/core/collections/45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb/defaultAccessConditions',
logo: 'https://rest.api/dspace-spring-rest/api/core/collections/45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb/logo',
self: 'https://rest.api/dspace-spring-rest/api/core/collections/45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb'
}
},
item: {
handle: null,
lastModified: '2019-01-09T10:17:33.722+0000',
isArchived: false,
isDiscoverable: true,
isWithdrawn: false,
owningCollection: 'https://rest.api/dspace-spring-rest/api/core/items/cae8af78-c874-4468-af79-e6c996aa8270/owningCollection',
bitstreams: {
pageInfo: {
elementsPerPage: 0,
totalElements: 0,
totalPages: 1,
currentPage: 1
},
page: []
},
self: 'https://rest.api/dspace-spring-rest/api/core/items/cae8af78-c874-4468-af79-e6c996aa8270',
id: 'cae8af78-c874-4468-af79-e6c996aa8270',
uuid: 'cae8af78-c874-4468-af79-e6c996aa8270',
type: 'item',
name: null,
metadata: [],
_links: {
bitstreams: 'https://rest.api/dspace-spring-rest/api/core/items/cae8af78-c874-4468-af79-e6c996aa8270/bitstreams',
owningCollection: 'https://rest.api/dspace-spring-rest/api/core/items/cae8af78-c874-4468-af79-e6c996aa8270/owningCollection',
templateItemOf: 'https://rest.api/dspace-spring-rest/api/core/items/cae8af78-c874-4468-af79-e6c996aa8270/templateItemOf',
self: 'https://rest.api/dspace-spring-rest/api/core/items/cae8af78-c874-4468-af79-e6c996aa8270'
}
},
submissionDefinition: {
isDefault: true,
sections: {
pageInfo: {
elementsPerPage: 5,
totalElements: 5,
totalPages: 1,
currentPage: 1
},
page: [
{
mandatory: true,
sectionType: 'collection',
visibility: {
main: 'HIDDEN',
other: 'HIDDEN'
},
type: 'submissionsection',
_links: {
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection'
},
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/collection'
},
{
header: 'submit.progressbar.describe.stepone',
mandatory: true,
sectionType: 'submission-form',
type: 'submissionsection',
_links: {
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone',
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone'
},
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpageone'
},
{
header: 'submit.progressbar.describe.steptwo',
mandatory: true,
sectionType: 'submission-form',
type: 'submissionsection',
_links: {
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo',
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo'
},
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/traditionalpagetwo'
},
{
header: 'submit.progressbar.upload',
mandatory: true,
sectionType: 'upload',
type: 'submissionsection',
_links: {
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload',
config: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload'
},
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/upload'
},
{
header: 'submit.progressbar.license',
mandatory: true,
sectionType: 'license',
visibility: {
main: null,
other: 'READONLY'
},
type: 'submissionsection',
_links: {
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license'
},
self: 'https://rest.api/dspace-spring-rest/api/config/submissionsections/license'
}
]
},
name: 'traditionaltwo',
type: 'submissiondefinition',
_links: {
collections: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional/collections',
sections: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional/sections',
self: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional'
},
self: 'https://rest.api/dspace-spring-rest/api/config/submissiondefinitions/traditional',
collections: {
pageInfo: {
elementsPerPage: 0,
totalElements: 0,
totalPages: 1,
currentPage: 1
},
page: []
}
},
submitter: {
handle: null,
groups: [],
netid: null,
lastActive: '2019-01-09T10:17:33.047+0000',
canLogIn: true,
email: 'dspacedemo+submit@gmail.com',
requireCertificate: false,
selfRegistered: false,
self: 'https://rest.api/dspace-spring-rest/api/eperson/epersons/99423c27-b642-4bb9-a9cd-45gh23e68dca5',
id: '99423c27-b642-4bb9-a9cd-45gh23e68dca5',
uuid: '99423c27-b642-4bb9-a9cd-45gh23e68dca5',
type: 'eperson',
name: 'dspacedemo+submit@gmail.com',
metadata: [
{
key: 'eperson.firstname',
language: null,
value: 'Demo'
},
{
key: 'eperson.lastname',
language: null,
value: 'Submitter'
}
],
_links: {
self: 'https://rest.api/dspace-spring-rest/api/eperson/epersons/99423c27-b642-4bb9-a9cd-45gh23e68dca5'
}
},
id: 826,
lastModified: '2019-01-09T10:17:33.738+0000',
sections: {},
errors: [],
self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826',
type: 'workspaceitem',
_links: {
collection: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/collection',
item: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/item',
submissionDefinition: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/submissionDefinition',
submitter: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826/submitter',
self: 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826'
}
};
export const mockSubmissionCollectionId = '1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb'; export const mockSubmissionCollectionId = '1c11f3f1-ba1f-4f36-908a-3f1ea9a557eb';
export const mockSubmissionId = '826'; export const mockSubmissionId = '826';
export const mockSubmissionSelfUrl = 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826'; export const mockSubmissionSelfUrl = 'https://rest.api/dspace-spring-rest/api/submission/workspaceitems/826';
export const mockSubmissionDefinitionResponse = { export const mockSubmissionDefinitionResponse = {
@@ -801,3 +1107,127 @@ export const mockSubmissionState: SubmissionObjectState = {
depositPending: false depositPending: false
} }
}; };
export const mockSectionsState = {
extraction: {
config: '',
mandatory: true,
sectionType: 'utils',
visibility: {
main: 'HIDDEN',
other: 'HIDDEN'
},
collapsed: false,
enabled: true,
data: {},
errors: [],
isLoading: false,
isValid: false
} as any,
collection: {
config: '',
mandatory: true,
sectionType: 'collection',
visibility: {
main: 'HIDDEN',
other: 'HIDDEN'
},
collapsed: false,
enabled: true,
data: {},
errors: [],
isLoading: false,
isValid: false
} as any,
traditionalpageone: {
header: 'submit.progressbar.describe.stepone',
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone',
mandatory: true,
sectionType: 'submission-form',
collapsed: false,
enabled: true,
data: {},
errors: [],
isLoading: false,
isValid: false
} as any,
traditionalpagetwo: {
header: 'submit.progressbar.describe.steptwo',
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo',
mandatory: false,
sectionType: 'submission-form',
collapsed: false,
enabled: false,
data: {},
errors: [],
isLoading: false,
isValid: false
} as any,
upload: {
header: 'submit.progressbar.upload',
config: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload',
mandatory: true,
sectionType: 'upload',
collapsed: false,
enabled: true,
data: {},
errors: [],
isLoading: false,
isValid: false
} as any,
license: {
header: 'submit.progressbar.license',
config: '',
mandatory: true,
sectionType: 'license',
visibility: {
main: null,
other: 'READONLY'
},
collapsed: false,
enabled: true,
data: {},
errors: [],
isLoading: false,
isValid: false
} as any
};
export const mockSectionsList = [
{
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone',
mandatory: true,
data: {},
errors: [],
header: 'submit.progressbar.describe.stepone',
id: 'traditionalpageone',
sectionType: 'submission-form'
},
{
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpagetwo',
mandatory: true,
data: {},
errors: [],
header: 'submit.progressbar.describe.steptwo',
id: 'traditionalpagetwo',
sectionType: 'submission-form'
},
{
config: 'https://rest.api/dspace-spring-rest/api/config/submissionuploads/upload',
mandatory: true,
data: {},
errors: [],
header: 'submit.progressbar.upload',
id: 'upload',
sectionType: 'upload'
},
{
config: '',
mandatory: true,
data: {},
errors: [],
header: 'submit.progressbar.license',
id: 'license',
sectionType: 'license'
}
];

View File

@@ -10,10 +10,10 @@
class="btn btn-outline-primary" class="btn btn-outline-primary"
(blur)="onClose()" (blur)="onClose()"
(click)="onClose()" (click)="onClose()"
[disabled]="disabled" [disabled]="(disabled$ | async)"
ngbDropdownToggle> ngbDropdownToggle>
<span *ngIf="disabled"><i class='fas fa-circle-notch fa-spin'></i></span> <span *ngIf="(disabled$ | async)"><i class='fas fa-circle-notch fa-spin'></i></span>
<span *ngIf="!disabled">{{ (selectedCollectionName) ? selectedCollectionName : '' }}</span> <span *ngIf="!(disabled$ | async)">{{ (selectedCollectionName) ? selectedCollectionName : '' }}</span>
</button> </button>
<div ngbDropdownMenu <div ngbDropdownMenu
@@ -30,7 +30,7 @@
</div> </div>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<div class="scrollable-menu" aria-labelledby="dropdownMenuButton" (scroll)="onScroll($event)"> <div class="scrollable-menu" aria-labelledby="dropdownMenuButton" (scroll)="onScroll($event)">
<button class="dropdown-item disabled" *ngIf="(searchListCollection$ | async).length == 0"> <button class="dropdown-item disabled" *ngIf="(searchListCollection$ | async)?.length == 0">
{{'submission.sections.general.no-collection' | translate}} {{'submission.sections.general.no-collection' | translate}}
</button> </button>
<button *ngFor="let listItem of (searchListCollection$ | async)" <button *ngFor="let listItem of (searchListCollection$ | async)"

View File

@@ -0,0 +1,353 @@
import { ChangeDetectorRef, CUSTOM_ELEMENTS_SCHEMA, DebugElement, SimpleChange } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { of as observableOf } from 'rxjs';
import { filter } from 'rxjs/operators';
import { TranslateModule } from '@ngx-translate/core';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { Store } from '@ngrx/store';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service-stub';
import { mockSubmissionId, mockSubmissionRestResponse } from '../../../shared/mocks/mock-submission';
import { SubmissionService } from '../../submission.service';
import { SubmissionFormCollectionComponent } from './submission-form-collection.component';
import { CommunityDataService } from '../../../core/data/community-data.service';
import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service';
import { SubmissionJsonPatchOperationsServiceStub } from '../../../shared/testing/submission-json-patch-operations-service-stub';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { Community } from '../../../core/shared/community.model';
import { RemoteData } from '../../../core/data/remote-data';
import { PaginatedList } from '../../../core/data/paginated-list';
import { PageInfo } from '../../../core/shared/page-info.model';
import { Collection } from '../../../core/shared/collection.model';
const subcommunities = [Object.assign(new Community(), {
name: 'SubCommunity 1',
id: '123456789-1',
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'SubCommunity 1'
}]
}),
Object.assign(new Community(), {
name: 'SubCommunity 1',
id: '123456789s-1',
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'SubCommunity 1'
}]
})
];
const mockCommunity1Collection1 = Object.assign(new Collection(), {
name: 'Community 1-Collection 1',
id: '1234567890-1',
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'Community 1-Collection 1'
}]
});
const mockCommunity1Collection2 = Object.assign(new Collection(), {
name: 'Community 1-Collection 2',
id: '1234567890-2',
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'Community 1-Collection 2'
}]
});
const mockCommunity2Collection1 = Object.assign(new Collection(), {
name: 'Community 2-Collection 1',
id: '1234567890-3',
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'Community 2-Collection 1'
}]
});
const mockCommunity2Collection2 = Object.assign(new Collection(), {
name: 'Community 2-Collection 2',
id: '1234567890-4',
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'Community 2-Collection 2'
}]
});
const mockCommunity = Object.assign(new Community(), {
name: 'Community 1',
id: '123456789-1',
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'Community 1'
}],
collections: observableOf(new RemoteData(true, true, true,
undefined, new PaginatedList(new PageInfo(), [mockCommunity1Collection1, mockCommunity1Collection2]))),
subcommunities: observableOf(new RemoteData(true, true, true,
undefined, new PaginatedList(new PageInfo(), subcommunities))),
});
const mockCommunity2 = Object.assign(new Community(), {
name: 'Community 2',
id: '123456789-2',
metadata: [
{
key: 'dc.title',
language: 'en_US',
value: 'Community 2'
}],
collections: observableOf(new RemoteData(true, true, true,
undefined, new PaginatedList(new PageInfo(), [mockCommunity2Collection1, mockCommunity2Collection2]))),
subcommunities: observableOf(new RemoteData(true, true, true,
undefined, new PaginatedList(new PageInfo(), []))),
});
const mockCommunityList = observableOf(new RemoteData(true, true, true,
undefined, new PaginatedList(new PageInfo(), [mockCommunity, mockCommunity2])));
const mockCollectionList = [
{
communities: [
{
id: '123456789-1',
name: 'Community 1'
}
],
collection: {
id: '1234567890-1',
name: 'Community 1-Collection 1'
}
},
{
communities: [
{
id: '123456789-1',
name: 'Community 1'
}
],
collection: {
id: '1234567890-2',
name: 'Community 1-Collection 2'
}
},
{
communities: [
{
id: '123456789-2',
name: 'Community 2'
}
],
collection: {
id: '1234567890-3',
name: 'Community 2-Collection 1'
}
},
{
communities: [
{
id: '123456789-2',
name: 'Community 2'
}
],
collection: {
id: '1234567890-4',
name: 'Community 2-Collection 2'
}
}
];
describe('SubmissionFormCollectionComponent Component', () => {
let comp: SubmissionFormCollectionComponent;
let compAsAny: any;
let fixture: ComponentFixture<SubmissionFormCollectionComponent>;
let submissionServiceStub: SubmissionServiceStub;
let jsonPatchOpServiceStub: SubmissionJsonPatchOperationsServiceStub;
const submissionId = mockSubmissionId;
const collectionId = '1234567890-1';
const definition = 'traditional';
const submissionRestResponse = mockSubmissionRestResponse;
const communityDataService: any = jasmine.createSpyObj('communityDataService', {
findAll: jasmine.createSpy('findAll')
});
const store: any = jasmine.createSpyObj('store', {
dispatch: jasmine.createSpy('dispatch'),
select: jasmine.createSpy('select')
});
const jsonPatchOpBuilder: any = jasmine.createSpyObj('jsonPatchOpBuilder', {
replace: jasmine.createSpy('replace')
});
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
FormsModule,
ReactiveFormsModule,
NgbModule.forRoot(),
TranslateModule.forRoot()
],
declarations: [SubmissionFormCollectionComponent],
providers: [
{ provide: SubmissionJsonPatchOperationsService, useClass: SubmissionJsonPatchOperationsServiceStub },
{ provide: SubmissionService, useClass: SubmissionServiceStub },
{ provide: CommunityDataService, useValue: communityDataService },
{ provide: JsonPatchOperationsBuilder, useValue: jsonPatchOpBuilder },
{ provide: Store, useValue: store },
ChangeDetectorRef
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SubmissionFormCollectionComponent);
comp = fixture.componentInstance;
compAsAny = comp;
submissionServiceStub = TestBed.get(SubmissionService);
jsonPatchOpServiceStub = TestBed.get(SubmissionJsonPatchOperationsService);
comp.currentCollectionId = collectionId;
comp.currentDefinition = definition;
comp.submissionId = submissionId;
});
afterEach(() => {
comp = null;
compAsAny = null;
fixture = null;
submissionServiceStub = null;
jsonPatchOpServiceStub = null;
});
it('should init JsonPatchOperationPathCombiner', () => {
const expected = new JsonPatchOperationPathCombiner('sections', 'collection');
fixture.detectChanges();
expect(compAsAny.pathCombiner).toEqual(expected);
});
it('should init collection list properly', () => {
communityDataService.findAll.and.returnValue(mockCommunityList);
comp.ngOnChanges({
currentCollectionId: new SimpleChange(null, collectionId, true)
});
comp.searchListCollection$.pipe(
filter(() => !comp.disabled$.getValue())
).subscribe((list) => {
expect(list).toEqual(mockCollectionList);
})
});
it('should show only the searched collection', () => {
comp.searchListCollection$ = observableOf(mockCollectionList);
fixture.detectChanges();
comp.searchField.patchValue('Community 2-Collection 2');
fixture.detectChanges();
comp.searchListCollection$.pipe(
filter(() => !comp.disabled$.getValue())
).subscribe((list) => {
expect(list).toEqual([mockCollectionList[3]]);
})
});
it('should emit collectionChange event when selecting a new collection', () => {
spyOn(comp.searchField, 'reset').and.callThrough();
spyOn(comp.collectionChange, 'emit').and.callThrough();
jsonPatchOpServiceStub.jsonPatchByResourceID.and.returnValue(observableOf(submissionRestResponse));
comp.ngOnInit();
comp.onSelect(mockCollectionList[1]);
fixture.detectChanges();
expect(comp.searchField.reset).toHaveBeenCalled();
expect(comp.collectionChange.emit).toHaveBeenCalledWith(submissionRestResponse[0]);
expect(submissionServiceStub.changeSubmissionCollection).toHaveBeenCalled();
expect(comp.selectedCollectionId).toBe(mockCollectionList[1].collection.id);
expect(comp.selectedCollectionName).toBe(mockCollectionList[1].collection.name);
});
it('should reset searchField when dropdown menu has been closed', () => {
spyOn(comp.searchField, 'reset').and.callThrough();
comp.toggled(false);
expect(comp.searchField.reset).toHaveBeenCalled();
});
describe('', () => {
let dropdowBtn: DebugElement;
let dropdownMenu: DebugElement;
beforeEach(() => {
comp.searchListCollection$ = observableOf(mockCollectionList);
fixture.detectChanges();
dropdowBtn = fixture.debugElement.query(By.css('#collectionControlsMenuButton'));
dropdownMenu = fixture.debugElement.query(By.css('#collectionControlsDropdownMenu'));
});
it('should have dropdown menu closed', () => {
expect(dropdowBtn).not.toBeUndefined();
expect(dropdownMenu.nativeElement.classList).not.toContain('show');
});
it('should display dropdown menu when click on dropdown button', fakeAsync(() => {
spyOn(comp, 'onClose');
dropdowBtn.triggerEventHandler('click', null);
tick();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(comp.onClose).toHaveBeenCalled();
expect(dropdownMenu.nativeElement.classList).toContain('show');
expect(dropdownMenu.queryAll(By.css('.collection-item')).length).toBe(4);
});
}));
it('should trigger onSelect method when select a new collection from dropdown menu', fakeAsync(() => {
spyOn(comp, 'onSelect');
dropdowBtn.triggerEventHandler('click', null);
tick();
fixture.detectChanges();
const secondLink: DebugElement = dropdownMenu.query(By.css('.collection-item:nth-child(2)'));
secondLink.triggerEventHandler('click', null);
tick();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(comp.onSelect).toHaveBeenCalled();
});
}));
});
});

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { combineLatest, Observable, Subscription } from 'rxjs'; import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
import { import {
debounceTime, debounceTime,
distinctUntilChanged, distinctUntilChanged,
@@ -29,7 +29,7 @@ import { isNullOrUndefined } from 'util';
import { Collection } from '../../../core/shared/collection.model'; import { Collection } from '../../../core/shared/collection.model';
import { CommunityDataService } from '../../../core/data/community-data.service'; import { CommunityDataService } from '../../../core/data/community-data.service';
import { Community } from '../../../core/shared/community.model'; import { Community } from '../../../core/shared/community.model';
import { hasValue, isNotEmpty } from '../../../shared/empty.util'; import { hasValue, isNotEmpty, isEmpty } from '../../../shared/empty.util';
import { RemoteData } from '../../../core/data/remote-data'; import { RemoteData } from '../../../core/data/remote-data';
import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner'; import { JsonPatchOperationPathCombiner } from '../../../core/json-patch/builder/json-patch-operation-path-combiner';
import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder'; import { JsonPatchOperationsBuilder } from '../../../core/json-patch/builder/json-patch-operations-builder';
@@ -65,7 +65,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
*/ */
@Output() collectionChange: EventEmitter<Workspaceitem> = new EventEmitter<Workspaceitem>(); @Output() collectionChange: EventEmitter<Workspaceitem> = new EventEmitter<Workspaceitem>();
public disabled = true; public disabled$ = new BehaviorSubject<boolean>(true);
public model: any; public model: any;
public searchField: FormControl = new FormControl(); public searchField: FormControl = new FormControl();
public searchListCollection$: Observable<CollectionListEntry[]>; public searchListCollection$: Observable<CollectionListEntry[]>;
@@ -103,7 +103,6 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (hasValue(changes.currentCollectionId) if (hasValue(changes.currentCollectionId)
&& hasValue(changes.currentCollectionId.currentValue)) { && hasValue(changes.currentCollectionId.currentValue)) {
this.selectedCollectionId = this.currentCollectionId; this.selectedCollectionId = this.currentCollectionId;
// @TODO replace with search/top browse endpoint // @TODO replace with search/top browse endpoint
// @TODO implement community/subcommunity hierarchy // @TODO implement community/subcommunity hierarchy
@@ -129,11 +128,6 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
); );
}), }),
reduce((acc: any, value: any) => [...acc, ...value], []), reduce((acc: any, value: any) => [...acc, ...value], []),
tap((list: CollectionListEntry[]) => {
if (isNotEmpty(list)) {
this.disabled = false;
}
}),
startWith([]) startWith([])
); );
@@ -145,6 +139,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
this.searchListCollection$ = combineLatest(searchTerm$, listCollection$).pipe( this.searchListCollection$ = combineLatest(searchTerm$, listCollection$).pipe(
map(([searchTerm, listCollection]) => { map(([searchTerm, listCollection]) => {
this.disabled$.next(isEmpty(listCollection));
if (searchTerm === '' || isNullOrUndefined(searchTerm)) { if (searchTerm === '' || isNullOrUndefined(searchTerm)) {
return listCollection; return listCollection;
} else { } else {
@@ -164,7 +159,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
onSelect(event) { onSelect(event) {
this.searchField.reset(); this.searchField.reset();
this.disabled = true; this.disabled$.next(true);
this.operationsBuilder.replace(this.pathCombiner.getPath(), event.collection.id, true); this.operationsBuilder.replace(this.pathCombiner.getPath(), event.collection.id, true);
this.subs.push(this.operationsService.jsonPatchByResourceID( this.subs.push(this.operationsService.jsonPatchByResourceID(
this.submissionService.getSubmissionObjectLinkName(), this.submissionService.getSubmissionObjectLinkName(),
@@ -176,7 +171,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
this.selectedCollectionName = event.collection.name; this.selectedCollectionName = event.collection.name;
this.collectionChange.emit(submissionObject[0]); this.collectionChange.emit(submissionObject[0]);
this.submissionService.changeSubmissionCollection(this.submissionId, event.collection.id); this.submissionService.changeSubmissionCollection(this.submissionId, event.collection.id);
this.disabled = false; this.disabled$.next(false);
this.cdr.detectChanges(); this.cdr.detectChanges();
}) })
); );

View File

@@ -0,0 +1,195 @@
import { ChangeDetectorRef, NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of as observableOf } from 'rxjs';
import { cold, hot } from 'jasmine-marbles';
import { TranslateModule } from '@ngx-translate/core';
import { NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { Store } from '@ngrx/store';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service-stub';
import { mockSubmissionId } from '../../../shared/mocks/mock-submission';
import { SubmissionService } from '../../submission.service';
import { SubmissionRestServiceStub } from '../../../shared/testing/submission-rest-service-stub';
import { SubmissionFormFooterComponent } from './submission-form-footer.component';
import { SubmissionRestService } from '../../submission-rest.service';
describe('SubmissionFormFooterComponent Component', () => {
let comp: SubmissionFormFooterComponent;
let compAsAny: any;
let fixture: ComponentFixture<SubmissionFormFooterComponent>;
let submissionServiceStub: SubmissionServiceStub;
let submissionRestServiceStub: SubmissionRestServiceStub;
const submissionId = mockSubmissionId;
const store: any = jasmine.createSpyObj('store', {
dispatch: jasmine.createSpy('dispatch'),
select: jasmine.createSpy('select')
});
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
NgbModule.forRoot(),
TranslateModule.forRoot()
],
declarations: [SubmissionFormFooterComponent],
providers: [
{ provide: SubmissionService, useClass: SubmissionServiceStub },
{ provide: SubmissionRestService, useClass: SubmissionRestServiceStub },
{ provide: Store, useValue: store },
ChangeDetectorRef,
NgbModal
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SubmissionFormFooterComponent);
comp = fixture.componentInstance;
compAsAny = comp;
submissionServiceStub = TestBed.get(SubmissionService);
submissionRestServiceStub = TestBed.get(SubmissionRestService);
comp.submissionId = submissionId;
});
afterEach(() => {
comp = null;
compAsAny = null;
fixture = null;
submissionServiceStub = null;
submissionRestServiceStub = null;
});
describe('ngOnChanges', () => {
beforeEach(() => {
submissionServiceStub.getSubmissionStatus.and.returnValue(hot('-a-b', {
a: false,
b: true
}));
submissionServiceStub.getSubmissionSaveProcessingStatus.and.returnValue(hot('-a-b', {
a: false,
b: true
}));
submissionServiceStub.getSubmissionDepositProcessingStatus.and.returnValue(hot('-a-b', {
a: false,
b: true
}));
});
it('should set submissionIsInvalid properly', () => {
const expected = cold('-c-d', {
c: true,
d: false
});
comp.ngOnChanges({
submissionId: new SimpleChange(null, submissionId, true)
});
fixture.detectChanges();
expect(compAsAny.submissionIsInvalid).toBeObservable(expected);
});
it('should set processingSaveStatus properly', () => {
const expected = cold('-c-d', {
c: false,
d: true
});
comp.ngOnChanges({
submissionId: new SimpleChange(null, submissionId, true)
});
fixture.detectChanges();
expect(comp.processingSaveStatus).toBeObservable(expected);
});
it('should set processingDepositStatus properly', () => {
const expected = cold('-c-d', {
c: false,
d: true
});
comp.ngOnChanges({
submissionId: new SimpleChange(null, submissionId, true)
});
fixture.detectChanges();
expect(comp.processingDepositStatus).toBeObservable(expected);
});
});
it('should call dispatchSave on save', () => {
comp.save(null);
fixture.detectChanges();
expect(submissionServiceStub.dispatchSave).toHaveBeenCalledWith(submissionId);
});
it('should call dispatchSaveForLater on save for later', () => {
comp.saveLater(null);
fixture.detectChanges();
expect(submissionServiceStub.dispatchSaveForLater).toHaveBeenCalledWith(submissionId);
});
it('should call dispatchDeposit on save', () => {
comp.deposit(null);
fixture.detectChanges();
expect(submissionServiceStub.dispatchDeposit).toHaveBeenCalledWith(submissionId);
});
it('should call dispatchDiscard on discard confirmation', fakeAsync(() => {
comp.showDepositAndDiscard = observableOf(true);
fixture.detectChanges();
const modalBtn = fixture.debugElement.query(By.css('.btn-danger'));
modalBtn.nativeElement.click();
fixture.detectChanges();
const confirmBtn: any = ((document as any).querySelector('.btn-danger:nth-child(2)'));
confirmBtn.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(submissionServiceStub.dispatchDiscard).toHaveBeenCalledWith(submissionId);
});
}));
it('should have deposit button disabled when submission is not valid', () => {
comp.showDepositAndDiscard = observableOf(true);
compAsAny.submissionIsInvalid = observableOf(true);
fixture.detectChanges();
const depositBtn: any = fixture.debugElement.query(By.css('.btn-primary'));
expect(depositBtn.nativeElement.disabled).toBeTruthy();
});
it('should not have deposit button disabled when submission is valid', () => {
comp.showDepositAndDiscard = observableOf(true);
compAsAny.submissionIsInvalid = observableOf(false);
fixture.detectChanges();
const depositBtn: any = fixture.debugElement.query(By.css('.btn-primary'));
expect(depositBtn.nativeElement.disabled).toBeFalsy();
});
});

View File

@@ -0,0 +1,168 @@
import { ChangeDetectorRef, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { of as observableOf } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { Store } from '@ngrx/store';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service-stub';
import { mockSubmissionCollectionId, mockSubmissionId } from '../../../shared/mocks/mock-submission';
import { SubmissionService } from '../../submission.service';
import { SubmissionFormSectionAddComponent } from './submission-form-section-add.component';
import { SectionsServiceStub } from '../../../shared/testing/sections-service-stub';
import { SectionsService } from '../../sections/sections.service';
import { HostWindowServiceStub } from '../../../shared/testing/host-window-service-stub';
import { HostWindowService } from '../../../shared/host-window.service';
const mockAvailableSections: any = [
{
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/newsectionone',
mandatory: true,
data: {},
errors: [],
header: 'submit.progressbar.describe.newsectionone',
id: 'newsectionone',
sectionType: 'submission-form'
},
{
config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/newsectiontwo',
mandatory: true,
data: {},
errors: [],
header: 'submit.progressbar.describe.newsectiontwo',
id: 'newsectiontwo',
sectionType: 'submission-form'
}
];
describe('SubmissionFormFooterComponent Component', () => {
let comp: SubmissionFormSectionAddComponent;
let compAsAny: any;
let fixture: ComponentFixture<SubmissionFormSectionAddComponent>;
let submissionServiceStub: SubmissionServiceStub;
let sectionsServiceStub: SectionsServiceStub;
const submissionId = mockSubmissionId;
const collectionId = mockSubmissionCollectionId;
const store: any = jasmine.createSpyObj('store', {
dispatch: jasmine.createSpy('dispatch'),
select: jasmine.createSpy('select')
});
const window = new HostWindowServiceStub(800);
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
NgbModule.forRoot(),
TranslateModule.forRoot()
],
declarations: [SubmissionFormSectionAddComponent],
providers: [
{ provide: HostWindowService, useValue: window },
{ provide: SubmissionService, useClass: SubmissionServiceStub },
{ provide: SectionsService, useClass: SectionsServiceStub },
{ provide: Store, useValue: store },
ChangeDetectorRef
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SubmissionFormSectionAddComponent);
comp = fixture.componentInstance;
compAsAny = comp;
submissionServiceStub = TestBed.get(SubmissionService);
sectionsServiceStub = TestBed.get(SectionsService);
comp.submissionId = submissionId;
comp.collectionId = collectionId;
});
afterEach(() => {
comp = null;
compAsAny = null;
fixture = null;
submissionServiceStub = null;
sectionsServiceStub = null;
});
it('should init sectionList properly', () => {
submissionServiceStub.getDisabledSectionsList.and.returnValue(observableOf(mockAvailableSections));
fixture.detectChanges();
comp.sectionList.subscribe((list) => {
expect(list).toEqual(mockAvailableSections);
})
});
it('should call addSection', () => {
comp.addSection(mockAvailableSections[1].id);
fixture.detectChanges();
expect(sectionsServiceStub.addSection).toHaveBeenCalledWith(submissionId, mockAvailableSections[1].id);
});
describe('', () => {
let dropdowBtn: DebugElement;
let dropdownMenu: DebugElement;
beforeEach(() => {
submissionServiceStub.getDisabledSectionsList.and.returnValue(observableOf(mockAvailableSections));
comp.ngOnInit();
fixture.detectChanges();
dropdowBtn = fixture.debugElement.query(By.css('#sectionControls'));
dropdownMenu = fixture.debugElement.query(By.css('.sections-dropdown-menu'));
});
it('should have dropdown menu closed', () => {
expect(dropdowBtn).not.toBeUndefined();
expect(dropdownMenu.nativeElement.classList).not.toContain('show');
});
it('should display dropdown menu when click on dropdown button', fakeAsync(() => {
dropdowBtn.triggerEventHandler('click', null);
tick();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(dropdownMenu.nativeElement.classList).toContain('show');
expect(dropdownMenu.queryAll(By.css('.dropdown-item')).length).toBe(2);
});
}));
it('should trigger onSelect method when select a new collection from dropdown menu', fakeAsync(() => {
spyOn(comp, 'addSection');
dropdowBtn.triggerEventHandler('click', null);
tick();
fixture.detectChanges();
const secondLink: DebugElement = dropdownMenu.query(By.css('.dropdown-item:nth-child(2)'));
secondLink.triggerEventHandler('click', null);
tick();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(comp.addSection).toHaveBeenCalled();
});
}));
});
});

View File

@@ -0,0 +1,164 @@
import { ChangeDetectorRef, NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { SubmissionServiceStub } from '../../shared/testing/submission-service-stub';
import {
mockSectionsData,
mockSectionsList,
mockSubmissionCollectionId,
mockSubmissionDefinition,
mockSubmissionId,
mockSubmissionObject,
mockSubmissionObjectNew,
mockSubmissionSelfUrl,
mockSubmissionState
} from '../../shared/mocks/mock-submission';
import { SubmissionService } from '../submission.service';
import { SubmissionFormComponent } from './submission-form.component';
import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
import { AuthServiceStub } from '../../shared/testing/auth-service-stub';
import { AuthService } from '../../core/auth/auth.service';
import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub';
describe('SubmissionFormComponent Component', () => {
let comp: SubmissionFormComponent;
let compAsAny: any;
let fixture: ComponentFixture<SubmissionFormComponent>;
let submissionServiceStub: SubmissionServiceStub;
let authServiceStub: AuthServiceStub;
const submissionId = mockSubmissionId;
const collectionId = mockSubmissionCollectionId;
const submissionObjectNew: any = mockSubmissionObjectNew;
const submissionDefinition: any = mockSubmissionDefinition;
const submissionState: any = mockSubmissionState;
const selfUrl: any = mockSubmissionSelfUrl;
const sectionsList: any = mockSectionsList;
const sectionsData: any = mockSectionsData;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [SubmissionFormComponent],
providers: [
{ provide: AuthService, useClass: AuthServiceStub },
{ provide: HALEndpointService, useValue: new HALEndpointServiceStub('workspaceitems') },
{ provide: SubmissionService, useClass: SubmissionServiceStub },
ChangeDetectorRef
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SubmissionFormComponent);
comp = fixture.componentInstance;
compAsAny = comp;
submissionServiceStub = TestBed.get(SubmissionService);
authServiceStub = TestBed.get(AuthService);
});
afterEach(() => {
comp = null;
compAsAny = null;
fixture = null;
});
it('should not has effect when collectionId and submissionId are undefined', () => {
fixture.detectChanges();
expect(compAsAny.isActive).toBeTruthy();
expect(compAsAny.submissionSections).toBeUndefined();
comp.loading.subscribe((loading) => {
expect(loading).toBeTruthy();
});
expect(compAsAny.subs).toEqual([]);
expect(submissionServiceStub.startAutoSave).not.toHaveBeenCalled();
});
it('should init properly when collectionId and submissionId are defined', () => {
comp.collectionId = collectionId;
comp.submissionId = submissionId;
comp.submissionDefinition = submissionDefinition;
comp.selfUrl = selfUrl;
comp.sections = sectionsData;
submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState));
submissionServiceStub.getSubmissionSections.and.returnValue(observableOf(sectionsList));
spyOn(authServiceStub, 'buildAuthHeader').and.returnValue('token');
comp.ngOnChanges({
collectionId: new SimpleChange(null, collectionId, true),
submissionId: new SimpleChange(null, submissionId, true)
});
fixture.detectChanges();
comp.loading.subscribe((loading) => {
expect(loading).toBeFalsy();
});
comp.submissionSections.subscribe((submissionSections) => {
expect(submissionSections).toEqual(sectionsList);
});
expect(submissionServiceStub.dispatchInit).toHaveBeenCalledWith(
collectionId,
submissionId,
selfUrl,
submissionDefinition,
sectionsData,
null);
expect(submissionServiceStub.startAutoSave).toHaveBeenCalled();
});
it('should update properly on collection change', () => {
comp.collectionId = collectionId;
comp.submissionId = submissionId;
comp.submissionDefinition = submissionDefinition;
comp.selfUrl = selfUrl;
comp.sections = sectionsData;
comp.onCollectionChange(submissionObjectNew);
fixture.detectChanges();
expect(comp.collectionId).toEqual(submissionObjectNew.collection.id);
expect(comp.submissionDefinition).toEqual(submissionObjectNew.submissionDefinition);
expect(comp.definitionId).toEqual(submissionObjectNew.submissionDefinition.name);
expect(comp.sections).toEqual(submissionObjectNew.sections);
expect(submissionServiceStub.resetSubmissionObject).toHaveBeenCalledWith(
submissionObjectNew.collection.id,
submissionId,
selfUrl,
submissionObjectNew.submissionDefinition,
submissionObjectNew.sections);
});
it('should update only collection id on collection change when submission definition is not changed', () => {
comp.collectionId = collectionId;
comp.submissionId = submissionId;
comp.definitionId = 'traditional';
comp.submissionDefinition = submissionDefinition;
comp.selfUrl = selfUrl;
comp.sections = sectionsData;
comp.onCollectionChange({
collection: {
id: '45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb'
},
submissionDefinition: {
name: 'traditional'
}
} as any);
fixture.detectChanges();
expect(comp.collectionId).toEqual('45f2f3f1-ba1f-4f36-908a-3f1ea9a557eb');
expect(submissionServiceStub.resetSubmissionObject).not.toHaveBeenCalled()
});
});

View File

@@ -0,0 +1,164 @@
import { ChangeDetectorRef, NO_ERRORS_SCHEMA } from '@angular/core';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { of as observableOf } from 'rxjs';
import { TranslateModule, TranslateService } from '@ngx-translate/core';
import { Store } from '@ngrx/store';
import { SubmissionServiceStub } from '../../../shared/testing/submission-service-stub';
import {
mockSectionsData,
mockSubmissionCollectionId,
mockSubmissionId,
mockSubmissionObject,
mockUploadResponse1ParsedErrors,
mockUploadResponse2Errors,
mockUploadResponse2ParsedErrors
} from '../../../shared/mocks/mock-submission';
import { SubmissionService } from '../../submission.service';
import { SectionsServiceStub } from '../../../shared/testing/sections-service-stub';
import { SectionsService } from '../../sections/sections.service';
import { SubmissionUploadFilesComponent } from './submission-upload-files.component';
import { NotificationsService } from '../../../shared/notifications/notifications.service';
import { NotificationsServiceStub } from '../../../shared/testing/notifications-service-stub';
import { getMockTranslateService } from '../../../shared/mocks/mock-translate.service';
import { cold, hot } from 'jasmine-marbles';
import { SubmissionJsonPatchOperationsServiceStub } from '../../../shared/testing/submission-json-patch-operations-service-stub';
import { SubmissionJsonPatchOperationsService } from '../../../core/submission/submission-json-patch-operations.service';
import { SharedModule } from '../../../shared/shared.module';
describe('SubmissionUploadFilesComponent Component', () => {
let comp: SubmissionUploadFilesComponent;
let compAsAny: any;
let fixture: ComponentFixture<SubmissionUploadFilesComponent>;
let submissionServiceStub: SubmissionServiceStub;
let sectionsServiceStub: SectionsServiceStub;
let notificationsServiceStub: NotificationsServiceStub;
let translateService: any;
const submissionJsonPatchOperationsServiceStub = new SubmissionJsonPatchOperationsServiceStub();
const submissionId = mockSubmissionId;
const collectionId = mockSubmissionCollectionId;
const uploadRestResponse: any = mockSubmissionObject;
const store: any = jasmine.createSpyObj('store', {
dispatch: jasmine.createSpy('dispatch'),
select: jasmine.createSpy('select')
});
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
SharedModule,
TranslateModule.forRoot()
],
declarations: [SubmissionUploadFilesComponent],
providers: [
{ provide: NotificationsService, useClass: NotificationsServiceStub },
{ provide: SubmissionService, useClass: SubmissionServiceStub },
{ provide: SectionsService, useClass: SectionsServiceStub },
{ provide: TranslateService, useValue: getMockTranslateService() },
{ provide: SubmissionJsonPatchOperationsService, useValue: submissionJsonPatchOperationsServiceStub },
{ provide: Store, useValue: store },
ChangeDetectorRef
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SubmissionUploadFilesComponent);
comp = fixture.componentInstance;
compAsAny = comp;
submissionServiceStub = TestBed.get(SubmissionService);
sectionsServiceStub = TestBed.get(SectionsService);
notificationsServiceStub = TestBed.get(NotificationsService);
translateService = TestBed.get(TranslateService);
comp.submissionId = submissionId;
comp.collectionId = collectionId;
comp.sectionId = 'upload';
comp.uploadFilesOptions = {
url: '',
authToken: null,
disableMultipart: false,
itemAlias: null
};
});
afterEach(() => {
comp = null;
compAsAny = null;
fixture = null;
submissionServiceStub = null;
sectionsServiceStub = null;
notificationsServiceStub = null;
translateService = null;
});
it('should init uploadEnabled properly', () => {
sectionsServiceStub.isSectionAvailable.and.returnValue(hot('-a-b', {
a: false,
b: true
}));
const expected = cold('-c-d', {
c: false,
d: true
});
comp.ngOnChanges();
fixture.detectChanges();
expect(compAsAny.uploadEnabled).toBeObservable(expected);
});
it('should show a success notification and call updateSectionData on upload complete', () => {
const expectedErrors: any = mockUploadResponse1ParsedErrors;
compAsAny.uploadEnabled = observableOf(true);
fixture.detectChanges();
comp.onCompleteItem(Object.assign({}, uploadRestResponse, { sections: mockSectionsData }));
Object.keys(mockSectionsData).forEach((sectionId) => {
expect(sectionsServiceStub.updateSectionData).toHaveBeenCalledWith(
submissionId,
sectionId,
mockSectionsData[sectionId],
expectedErrors[sectionId]
);
});
expect(notificationsServiceStub.success).toHaveBeenCalled();
});
it('should show an error notification and call updateSectionData on upload complete', () => {
const responseErrors = mockUploadResponse2Errors;
const expectedErrors: any = mockUploadResponse2ParsedErrors;
compAsAny.uploadEnabled = observableOf(true);
fixture.detectChanges();
comp.onCompleteItem(Object.assign({}, uploadRestResponse, {
sections: mockSectionsData,
errors: responseErrors.errors
}));
Object.keys(mockSectionsData).forEach((sectionId) => {
expect(sectionsServiceStub.updateSectionData).toHaveBeenCalledWith(
submissionId,
sectionId,
mockSectionsData[sectionId],
expectedErrors[sectionId]
);
});
expect(notificationsServiceStub.success).not.toHaveBeenCalled();
});
});

View File

@@ -32,7 +32,7 @@ import {
mockSubmissionId, mockSubmissionId,
mockSubmissionSelfUrl, mockSubmissionSelfUrl,
mockSubmissionState, mockSubmissionState,
submissionRestResponse mockSubmissionRestResponse
} from '../../shared/mocks/mock-submission'; } from '../../shared/mocks/mock-submission';
import { SubmissionSectionModel } from '../../core/config/models/config-submission-section.model'; import { SubmissionSectionModel } from '../../core/config/models/config-submission-section.model';
import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub'; import { NotificationsServiceStub } from '../../shared/testing/notifications-service-stub';
@@ -183,11 +183,11 @@ describe('SubmissionObjectEffects test suite', () => {
} }
}); });
submissionJsonPatchOperationsServiceStub.jsonPatchByResourceType.and.returnValue(observableOf(submissionRestResponse)); submissionJsonPatchOperationsServiceStub.jsonPatchByResourceType.and.returnValue(observableOf(mockSubmissionRestResponse));
const expected = cold('--b-', { const expected = cold('--b-', {
b: new SaveSubmissionFormSuccessAction( b: new SaveSubmissionFormSuccessAction(
submissionId, submissionId,
submissionRestResponse as any mockSubmissionRestResponse as any
) )
}); });
@@ -228,11 +228,11 @@ describe('SubmissionObjectEffects test suite', () => {
} }
}); });
submissionJsonPatchOperationsServiceStub.jsonPatchByResourceType.and.returnValue(observableOf(submissionRestResponse)); submissionJsonPatchOperationsServiceStub.jsonPatchByResourceType.and.returnValue(observableOf(mockSubmissionRestResponse));
const expected = cold('--b-', { const expected = cold('--b-', {
b: new SaveForLaterSubmissionFormSuccessAction( b: new SaveForLaterSubmissionFormSuccessAction(
submissionId, submissionId,
submissionRestResponse as any mockSubmissionRestResponse as any
) )
}); });
@@ -271,7 +271,7 @@ describe('SubmissionObjectEffects test suite', () => {
} }
} as any); } as any);
const response = [Object.assign({}, submissionRestResponse[0], { const response = [Object.assign({}, mockSubmissionRestResponse[0], {
sections: mockSectionsData, sections: mockSectionsData,
errors: mockSectionsErrors errors: mockSectionsErrors
})]; })];
@@ -319,7 +319,7 @@ describe('SubmissionObjectEffects test suite', () => {
} }
} as any); } as any);
const response = [Object.assign({}, submissionRestResponse[0], { const response = [Object.assign({}, mockSubmissionRestResponse[0], {
sections: mockSectionsData sections: mockSectionsData
})]; })];
actions = hot('--a-', { actions = hot('--a-', {
@@ -364,7 +364,7 @@ describe('SubmissionObjectEffects test suite', () => {
} }
} as any); } as any);
const response = [Object.assign({}, submissionRestResponse[0], { const response = [Object.assign({}, mockSubmissionRestResponse[0], {
sections: mockSectionsData, sections: mockSectionsData,
errors: mockSectionsErrors errors: mockSectionsErrors
})]; })];
@@ -411,7 +411,7 @@ describe('SubmissionObjectEffects test suite', () => {
} }
} as any); } as any);
const response = [Object.assign({}, submissionRestResponse[0], { const response = [Object.assign({}, mockSubmissionRestResponse[0], {
sections: mockSectionsDataTwo, sections: mockSectionsDataTwo,
errors: mockSectionsErrors errors: mockSectionsErrors
})]; })];
@@ -471,11 +471,11 @@ describe('SubmissionObjectEffects test suite', () => {
} }
}); });
submissionJsonPatchOperationsServiceStub.jsonPatchByResourceID.and.returnValue(observableOf(submissionRestResponse)); submissionJsonPatchOperationsServiceStub.jsonPatchByResourceID.and.returnValue(observableOf(mockSubmissionRestResponse));
const expected = cold('--b-', { const expected = cold('--b-', {
b: new SaveSubmissionSectionFormSuccessAction( b: new SaveSubmissionSectionFormSuccessAction(
submissionId, submissionId,
submissionRestResponse as any mockSubmissionRestResponse as any
) )
}); });
@@ -517,7 +517,7 @@ describe('SubmissionObjectEffects test suite', () => {
} }
}); });
const response = [Object.assign({}, submissionRestResponse[0], { const response = [Object.assign({}, mockSubmissionRestResponse[0], {
sections: mockSectionsDataTwo sections: mockSectionsDataTwo
})]; })];
@@ -547,7 +547,7 @@ describe('SubmissionObjectEffects test suite', () => {
} }
}); });
const response = [Object.assign({}, submissionRestResponse[0], { const response = [Object.assign({}, mockSubmissionRestResponse[0], {
sections: mockSectionsData, sections: mockSectionsData,
errors: mockSectionsErrors errors: mockSectionsErrors
})]; })];
@@ -621,7 +621,7 @@ describe('SubmissionObjectEffects test suite', () => {
} }
}); });
submissionServiceStub.depositSubmission.and.returnValue(observableOf(submissionRestResponse)); submissionServiceStub.depositSubmission.and.returnValue(observableOf(mockSubmissionRestResponse));
const expected = cold('--b-', { const expected = cold('--b-', {
b: new DepositSubmissionSuccessAction( b: new DepositSubmissionSuccessAction(
submissionId submissionId
@@ -667,7 +667,7 @@ describe('SubmissionObjectEffects test suite', () => {
type: SubmissionObjectActionTypes.SAVE_FOR_LATER_SUBMISSION_FORM_SUCCESS, type: SubmissionObjectActionTypes.SAVE_FOR_LATER_SUBMISSION_FORM_SUCCESS,
payload: { payload: {
submissionId: submissionId, submissionId: submissionId,
submissionObject: submissionRestResponse submissionObject: mockSubmissionRestResponse
} }
} }
}); });
@@ -731,7 +731,7 @@ describe('SubmissionObjectEffects test suite', () => {
} }
}); });
submissionServiceStub.discardSubmission.and.returnValue(observableOf(submissionRestResponse)); submissionServiceStub.discardSubmission.and.returnValue(observableOf(mockSubmissionRestResponse));
const expected = cold('--b-', { const expected = cold('--b-', {
b: new DiscardSubmissionSuccessAction( b: new DiscardSubmissionSuccessAction(
submissionId submissionId

View File

@@ -17,7 +17,7 @@ import { MockActivatedRoute } from '../shared/mocks/mock-active-router';
import { GLOBAL_CONFIG } from '../../config'; import { GLOBAL_CONFIG } from '../../config';
import { HttpOptions } from '../core/dspace-rest-v2/dspace-rest-v2.service'; import { HttpOptions } from '../core/dspace-rest-v2/dspace-rest-v2.service';
import { SubmissionScopeType } from '../core/submission/submission-scope-type'; import { SubmissionScopeType } from '../core/submission/submission-scope-type';
import { mockSubmissionDefinition, submissionRestResponse } from '../shared/mocks/mock-submission'; import { mockSubmissionDefinition, mockSubmissionRestResponse } from '../shared/mocks/mock-submission';
import { NotificationsService } from '../shared/notifications/notifications.service'; import { NotificationsService } from '../shared/notifications/notifications.service';
import { MockTranslateLoader } from '../shared/mocks/mock-translate-loader'; import { MockTranslateLoader } from '../shared/mocks/mock-translate-loader';
import { MOCK_SUBMISSION_CONFIG } from '../shared/testing/mock-submission-config'; import { MOCK_SUBMISSION_CONFIG } from '../shared/testing/mock-submission-config';
@@ -764,7 +764,7 @@ describe('SubmissionService test suite', () => {
describe('notifyNewSection', () => { describe('notifyNewSection', () => {
it('should return true/false when section is loading/not loading', fakeAsync(() => { it('should return true/false when section is loading/not loading', fakeAsync(() => {
const spy = spyOn((service as any).translate, 'get').and.returnValue(observableOf('test')); spyOn((service as any).translate, 'get').and.returnValue(observableOf('test'));
spyOn((service as any).notificationsService, 'info').and.callThrough(); spyOn((service as any).notificationsService, 'info').and.callThrough();
@@ -824,12 +824,12 @@ describe('SubmissionService test suite', () => {
describe('retrieveSubmission', () => { describe('retrieveSubmission', () => {
it('should retrieve submission from REST endpoint', () => { it('should retrieve submission from REST endpoint', () => {
(service as any).restService.getDataById.and.returnValue(hot('a|', { (service as any).restService.getDataById.and.returnValue(hot('a|', {
a: submissionRestResponse a: mockSubmissionRestResponse
})); }));
const result = service.retrieveSubmission('826'); const result = service.retrieveSubmission('826');
const expected = cold('(b|)', { const expected = cold('(b|)', {
b: submissionRestResponse[0] b: mockSubmissionRestResponse[0]
}); });
expect(result).toBeObservable(expected); expect(result).toBeObservable(expected);