Skip to content

Commit

Permalink
Merge pull request #852 from europeana/feat/MET-6036-Record-Reason-Fo…
Browse files Browse the repository at this point in the history
…r-Dataset-and-Record-Deletion

MET-6036 Add Reason for Dataset and Record Deletion
  • Loading branch information
andyjmaclean committed Jul 30, 2024
2 parents 2f21c1b + 4fc198c commit d84581d
Show file tree
Hide file tree
Showing 19 changed files with 452 additions and 176 deletions.
86 changes: 71 additions & 15 deletions projects/metis/cypress/e2e/depublications.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ context('metis-ui', () => {
const selMenuContentDepublish = '.dropdown-content.depublish';
const selMenuOpenAdd = '.dropdown-options.add > a';
const selMenuOpenDepublish = '.dropdown-options.depublish > a';
const selModalTitle = '.modal .head';
const selItemDRecords = `${selMenuContentDepublish} :first-child a`;
const selItemDDataset = `${selMenuContentDepublish} :last-child a`;

Expand All @@ -22,13 +23,24 @@ context('metis-ui', () => {
const selItemInput = `${selMenuContentAdd} :last-child a`;
const selLoadMore = '.tab-content .load-more-btn';

const submitEntries = (entries: string): void => {
const selSelectReason = '[name=depublicationReason]';
const testTexts = ['Test1', 'Test2'];

const submitEntriesOpen = (fileInput = false): void => {
cy.get(selMenuOpenAdd).click(force);
cy.get(selItemInput)
const selInput = fileInput ? selItemFile : selItemInput;
cy.get(selInput)
.scrollIntoView()
.click(force);
};

const submitEntries = (entries: string, submit = true): void => {
submitEntriesOpen();
cy.get('[name=recordIds]').type(entries);
cy.get('.modal [type="button"]').click();
cy.get(selSelectReason).select('GDPR');
if (submit) {
cy.get('.modal [type="submit"]').click();
}
cy.wait(100);
};

Expand Down Expand Up @@ -79,36 +91,42 @@ context('metis-ui', () => {

describe('forms', () => {
describe('successful operations', () => {
const modalTitle = 'Add record ids to depublish';

it('should open and close the file dialog form', () => {
cy.get(selDialogFile).should('not.exist');
cy.get(selMenuOpenAdd).click(force);
cy.get(selItemFile)
.scrollIntoView()
.click(force);
cy.get(selModalTitle).should('not.exist');
submitEntriesOpen(true);

cy.get(selModalTitle)
.contains(modalTitle)
.should('exist');
cy.get(selDialogFile).should('be.visible');
cy.get(selDialogClose).click();
cy.get(selDialogFile).should('not.exist');
cy.get(selModalTitle).should('not.exist');
});

it('should open and close the input dialog form', () => {
cy.get(selDialogInput).should('not.exist');
cy.get(selMenuOpenAdd).click(force);
cy.get(selItemInput)
.scrollIntoView()
.click(force);
cy.get(selModalTitle).should('not.exist');
submitEntriesOpen();

cy.get(selModalTitle)
.contains(modalTitle)
.should('exist');
cy.get(selDialogInput).should('be.visible');
cy.get(selDialogClose).click();

cy.get(selDialogInput).should('not.exist');
cy.get(selModalTitle).should('not.exist');
});

it('should submit new entries', () => {
const testTexts = ['Test1', 'Test2'];
submitEntries(testTexts.join('\n'));

testTexts.forEach((txt) => {
cy.get('.record-url')
cy.get('[data-e2e=record-id]')
.contains(txt)
.should('have.length', 1);
});
Expand Down Expand Up @@ -154,7 +172,7 @@ context('metis-ui', () => {
cy.screenshot();

testMore.slice(2).forEach((txt) => {
cy.get('.record-url')
cy.get('[data-e2e=record-id]')
.contains(txt)
.should('have.length', 1);
});
Expand Down Expand Up @@ -184,29 +202,67 @@ context('metis-ui', () => {
});

describe('confirmations', () => {
const modalTitle = 'Depublish';
const selDialogConfirm = '.modal-wrapper';
const selDialogConfirmClose = selDialogConfirm + ' .btn-close';
const selDialogConfirmClose = `${selDialogConfirm} .btn-close`;

it('should ask confirmation for dataset depublication', () => {
cy.get(selDialogConfirm).should('not.exist');
cy.wait(1000);
openDepublishMenu();
cy.get(selModalTitle).should('not.exist');
cy.get(selMenuContentDepublish).should('exist');

cy.get(selItemDDataset).click(force);
cy.get(selModalTitle)
.contains(modalTitle)
.should('exist');
cy.get(selDialogConfirm).should('be.visible');
cy.get(selSelectReason).should('exist');
cy.get(selSelectReason).should('be.visible');

cy.get(selDialogConfirmClose).click();
cy.get(selDialogConfirm).should('not.exist');
cy.get(selMenuContentDepublish).should('not.exist');
cy.get(selModalTitle).should('not.exist');
});

it('should clear filled fields when confirmation is not given', () => {
submitEntries(testTexts.join('\n'), false);
cy.get(selSelectReason).should('have.value', 'GDPR');
cy.get(selDialogConfirmClose).click();

// re-open form
submitEntriesOpen();
cy.get(selSelectReason).should('have.value', null);
});

it('should clear filled fields when confirmation is given', () => {
submitEntries(testTexts.join('\n'), true);

// re-open form
submitEntriesOpen();
cy.get(selSelectReason).should('have.value', null);
});

it('should ask confirmation for record id depublication', () => {
submitEntries(testTexts.join('\n'));
submitEntries('Test1\nTest2');
cy.get(selDialogConfirm).should('not.exist');
cy.get(selModalTitle).should('not.exist');
cy.wait(1000);
cy.get(selCheckbox).click({ force: true, multiple: true });
openDepublishMenu();
cy.get(selMenuContentDepublish).should('exist');
cy.get(selItemDRecords).click(force);
cy.get(selDialogConfirm).should('be.visible');
cy.get(selModalTitle)
.contains(modalTitle)
.should('exist');
cy.get(selDialogConfirmClose).click();
cy.get(selDialogConfirm).should('not.exist');
cy.get(selMenuContentDepublish).should('not.exist');
cy.get(selModalTitle).should('not.exist');
deleteVisibleEntries();
});
});
Expand Down
44 changes: 37 additions & 7 deletions projects/metis/src/app/_mocked/mockeddepublication.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import { HttpEvent } from '@angular/common/http';
import { Observable, of as observableOf, throwError, timer } from 'rxjs';
import { delay, switchMap } from 'rxjs/operators';

import { DatasetDepublicationInfo, DepublicationStatus, RecordDepublicationInfo } from '../_models';
import {
DatasetDepublicationInfo,
DepublicationReason,
DepublicationStatus,
RecordDepublicationInfo
} from '../_models';

export const mockPublicationInfo = [
{
Expand Down Expand Up @@ -59,9 +64,11 @@ export class MockDepublicationService {
return observableOf(true);
}

depublishDataset(datasetId: string): Observable<boolean> {
depublishDataset(datasetId: string, depublicationReason: string): Observable<boolean> {
if (this.errorMode) {
return throwError(new Error(`mock depublishDataset(${datasetId}) throws error...`));
return throwError(
new Error(`mock depublishDataset(${datasetId}/${depublicationReason}) throws error...`)
);
}
return observableOf(true);
}
Expand All @@ -75,27 +82,50 @@ export class MockDepublicationService {
return observableOf(true);
}

setPublicationFile(datasetId: string, file: File): Observable<boolean> {
setPublicationFile(
datasetId: string,
file: File,
depublicationReason: string
): Observable<boolean> {
if (this.errorMode) {
return timer(1).pipe(
switchMap(() => {
return throwError(
new Error(`mock setPublicationFile(${datasetId}, ${file}) throws error...`)
new Error(
`mock setPublicationFile(${datasetId}, ${file}, ${depublicationReason}) throws error...`
)
);
})
);
}
return observableOf(true).pipe(delay(1));
}

setPublicationInfo(datasetId: string, toDepublish: string): Observable<boolean> {
setPublicationInfo(
datasetId: string,
toDepublish: string,
depublicationReason: string
): Observable<boolean> {
if (this.errorMode) {
return throwError(
new Error(`mock setPublicationInfo(${datasetId}, ${toDepublish}) throws error...`)
new Error(
`mock setPublicationInfo(${datasetId}, ${toDepublish}, ${depublicationReason}) throws error...`
)
);
}
return observableOf(true);
}

getDepublicationReasons(): Observable<Array<DepublicationReason>> {
return observableOf(
['GDPS', 'etc.'].map((s: string) => {
return {
name: s,
valueAsString: s
};
})
);
}
}

export class MockDepublicationServiceErrors extends MockDepublicationService {
Expand Down
6 changes: 6 additions & 0 deletions projects/metis/src/app/_models/depublication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface RecordDepublicationInfo {
recordId: string;
depublicationStatus: DepublicationStatus;
depublicationDate?: string;
depublicationReason: string;
}

export interface RecordDepublicationInfoDeletable extends RecordDepublicationInfo {
Expand All @@ -31,6 +32,11 @@ export interface DepublicationDeletionInfo {
deletion: boolean;
}

export interface DepublicationReason {
valueAsString: string;
name: string;
}

export interface SortHeaderConf {
fieldName?: string;
translateKey?: string;
Expand Down
18 changes: 12 additions & 6 deletions projects/metis/src/app/_services/depublication.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@ describe('depublication service', () => {

it('should depublish a dataset', () => {
const id = '123';
const reason = 'GDPS';
let result = false;
const sub = service.depublishDataset(id).subscribe((res) => {
const sub = service.depublishDataset(id, reason).subscribe((res) => {
result = res;
});
mockHttp
.expect('POST', `/depublish/execute/${id}?datasetDepublish=true`)
.expect(
'POST',
`/depublish/execute/${id}?depublicationReason=${reason}&datasetDepublish=true`
)
.body(' ')
.send(' ');
sub.unsubscribe();
Expand Down Expand Up @@ -130,12 +134,13 @@ describe('depublication service', () => {

it('should set the publication info', () => {
let result = false;
const reason = 'GDPR';
const ids = 'http://depublish/record_ids/id1 http://depublish/record_ids/id2';
const sub = service.setPublicationInfo('123', ids).subscribe((res) => {
const sub = service.setPublicationInfo('123', ids, reason).subscribe((res) => {
result = res;
});
mockHttp
.expect('POST', '/depublish/record_ids/123')
.expect('POST', `/depublish/record_ids/123?depublicationReason=${reason}`)
.body(ids)
.send({ result: true });
sub.unsubscribe();
Expand All @@ -145,11 +150,12 @@ describe('depublication service', () => {
it('should set the publication file', () => {
spyOn(DepublicationService, 'handleUploadEvents');
const dsId = '123';
const reason = 'GDPR';
const file = { name: 'foo', size: 500001 } as File;
const sub = service.setPublicationFile(dsId, file).subscribe((res) => {
const sub = service.setPublicationFile(dsId, file, reason).subscribe((res) => {
expect(res).toBeFalsy();
});
const url = `/depublish/record_ids/${dsId}`;
const url = `/depublish/record_ids/${dsId}?depublicationReason=${reason}`;
const mockRequest = new MockHttpRequest(
({ flush: () => undefined, request: { body: {}, url: url } } as unknown) as TestRequest,
url
Expand Down
Loading

0 comments on commit d84581d

Please sign in to comment.