Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SUP-17881: Integration Tests #438

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion cms-ui/apps/editor-ui-e2e/src/e2e/media-management.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
TestSize,
minimalNode,
} from '@gentics/e2e-utils';
import { AUTH_ADMIN, FIXTURE_TEST_FILE_TXT_1, FIXTURE_TEST_IMAGE_JPG_1 } from '../support/common';
import { AUTH_ADMIN, FIXTURE_TEST_FILE_TXT_1, FIXTURE_TEST_IMAGE_JPG_1, FIXTURE_TEST_IMAGE_JPG_2 } from '../support/common';

describe('Media Management', () => {

Expand Down Expand Up @@ -115,4 +115,51 @@ describe('Media Management', () => {
});
});
});

it('should display the updated value even after switching object-properties', () => {
cy.uploadFiles(ITEM_TYPE_IMAGE, [FIXTURE_TEST_IMAGE_JPG_2]).then(allFiles => {
const IMAGE = allFiles[FIXTURE_TEST_IMAGE_JPG_2];
const OBJECT_PROPERTY_EDITING = 'test_color';
const OBJECT_PROPERTY_OTHER = 'copyright';

const COLOR_ID = 2;

/* Open the Folder Properties and select a Object-Property to edit
* ---------------------------- */
cy.findList(ITEM_TYPE_IMAGE)
.findItem(IMAGE.id)
.itemAction('properties');

cy.openObjectPropertyEditor(OBJECT_PROPERTY_EDITING)
.findTagEditorElement(TagPropertyType.SELECT)
.select(COLOR_ID);

/* Save the Object-Property changes
* ---------------------------- */
cy.intercept({
method: 'POST',
pathname: '/rest/image/save/**',
}, req => {
req.alias = ALIAS_UPDATE_REQUEST;
});

cy.editorAction('save');
// Wait for update to be finished
cy.wait(ALIAS_UPDATE_REQUEST);
// Wait 2sec for the state updates to propagate
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(2_000);

// Switch to another object-property
cy.openObjectPropertyEditor(OBJECT_PROPERTY_OTHER);
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(1_000);

// Switch back to the original one
cy.openObjectPropertyEditor(OBJECT_PROPERTY_EDITING)
.findTagEditorElement(TagPropertyType.SELECT)
.find('.view-value')
.should('have.attr', 'data-value', COLOR_ID);
});
});
});
42 changes: 23 additions & 19 deletions cms-ui/apps/editor-ui-e2e/src/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,38 +153,35 @@ Cypress.Commands.add('uploadFiles', { prevSubject: false }, (type, fixtureNames,
req.alias = `_upload_req_${fileName}`;
});

// Wait till elements have been reloaded
cy.intercept({
method: 'GET',
pathname: '/rest/folder/getPages/*',
}).as('folderLoad');

return cy.loadBinaries(fixtureNames, { applyAlias: true }).then(binaries => {
const output: Record<string, any> = {};
let main: Cypress.Chainable<any>;

if (options?.log !== false) {
Cypress.log({
type: 'parent',
name: 'upload files',
message: options?.dragAndDrop ? 'via drag and drop' : 'via regular upload',
consoleProps: () => ({
files: fixtureNames,
}),
});
}

if (options?.dragAndDrop) {
const transfer = new DataTransfer();
// Put the binaries/Files into the transfer
Object.values(binaries).forEach(file => {
transfer.items.add(file);
});

if (options?.log !== false) {
Cypress.log({
name: 'upload',
type: 'parent',
message: `via drag'n'drop: ${Object.values(binaries).map(bin => bin.name).join(', ')}`,
});
}

main = cy.get('folder-contents > [data-action="file-drop"]', { log: false }).trigger('drop', {
dataTransfer: transfer,
force: true,
log: false,
});
} else {
main = cy.findList(type)
main = cy.findList(type, { log: false })
.find('.list-header .header-controls [data-action="upload-item"] input[type="file"]', { log: false })
.selectFile(fixtureNames.map(entry => '@' + (typeof entry === 'string' ? entry : entry.fixturePath)), { force: true });
}
Expand All @@ -193,15 +190,22 @@ Cypress.Commands.add('uploadFiles', { prevSubject: false }, (type, fixtureNames,
for (const entry of fixtureNames) {
const data = normalizeToImportBinary(entry);

cy.wait(`@_upload_req_${data.name}`).then(intercept => {
cy.wait(`@_upload_req_${data.name}`, { log: false }).then(intercept => {
const res = intercept.response?.body;
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
expect(res.success).to.be.true;
expect(res.success).to.equal(true);
output[data.fixturePath] = res.file;

if (options?.log !== false) {
Cypress.log({
type: 'child',
name: 'file uploaded',
message: data.name,
});
}
});
}

return cy.wait('@folderLoad').then(() => cy.wrap(output, { log: false }));
return cy.wrap(output, { log: false });
})
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
ElasticSearchQuery,
ElasticSearchQueryResponse,
ElasticSearchTypeSearchOptions,
File,
File as CMSFile,
FileCopyRequest,
FileCreateRequest,
FileListResponse,
Expand Down Expand Up @@ -766,7 +766,7 @@ export class FolderActionsService {
/**
* Get an individual file.
*/
getFile(fileId: number): Promise<File<Raw>> {
getFile(fileId: number): Promise<CMSFile<Raw>> {
return this.getItem(fileId, 'file');
}

Expand Down Expand Up @@ -1169,7 +1169,7 @@ export class FolderActionsService {
getItem(itemId: number, type: 'folder', options?: FolderRequestOptions, throwError?: boolean): Promise<Folder<Raw>>;
getItem(itemId: number, type: 'page', options?: PageRequestOptions, throwError?: boolean): Promise<Page<Raw>>;
getItem(itemId: number, type: 'image', options?: ImageRequestOptions, throwError?: boolean): Promise<Image<Raw>>;
getItem(itemId: number, type: 'file', options?: FolderRequestOptions, throwError?: boolean): Promise<File<Raw>>;
getItem(itemId: number, type: 'file', options?: FolderRequestOptions, throwError?: boolean): Promise<CMSFile<Raw>>;
getItem(itemId: number, type: 'form', options?: FormRequestOptions, throwError?: boolean): Promise<Form<Raw>>;
getItem(itemId: number | string, type: 'template', options?: TemplateRequestOptions, throwError?: boolean): Promise<Template<Raw>>;
getItem(itemId: number | string, type: FolderItemOrTemplateType, options?: any, throwError?: boolean): Promise<InheritableItem<Raw> | Template<Raw>>;
Expand Down Expand Up @@ -1751,7 +1751,7 @@ export class FolderActionsService {
/**
* Update the editable properties of a file.
*/
updateFileProperties(fileId: number, properties: EditableFileProps, postUpdateBehavior?: PostUpdateBehavior): Promise<File<Raw> | void> {
updateFileProperties(fileId: number, properties: EditableFileProps, postUpdateBehavior?: PostUpdateBehavior): Promise<CMSFile<Raw> | void> {
return this.updateItem('file', fileId, properties, {}, postUpdateBehavior);
}

Expand Down Expand Up @@ -2045,7 +2045,7 @@ export class FolderActionsService {
}
}

localizeFile(fileId: number, channelId: number): Promise<File<Raw>> {
localizeFile(fileId: number, channelId: number): Promise<CMSFile<Raw>> {
return this.localizeItem('file', fileId, channelId);
}

Expand All @@ -2059,7 +2059,7 @@ export class FolderActionsService {
*/
localizeItem(type: 'folder', itemId: number, channelId: number): Promise<Folder<Raw>>;
localizeItem(type: 'page', itemId: number, channelId: number): Promise<Page<Raw>>;
localizeItem(type: 'file', itemId: number, channelId: number): Promise<File<Raw>>;
localizeItem(type: 'file', itemId: number, channelId: number): Promise<CMSFile<Raw>>;
localizeItem(type: 'image', itemId: number, channelId: number): Promise<Image<Raw>>;
localizeItem(type: FolderItemType, itemId: number, channelId: number): Promise<InheritableItem<Raw>>;
async localizeItem(type: FolderItemType, itemId: number, channelId: number): Promise<InheritableItem<Raw> | void> {
Expand Down Expand Up @@ -2491,7 +2491,7 @@ export class FolderActionsService {
* Copy a file or image to the target folder. Internally this creates a copy in the source folder and then
* moves the new object to the target folder.
*/
copyFilesToFolder(sourceFiles: File<Raw>[], sourceNodeId: number, targetFolderId: number, targetNodeId: number): Promise<boolean> {
copyFilesToFolder(sourceFiles: CMSFile<Raw>[], sourceNodeId: number, targetFolderId: number, targetNodeId: number): Promise<boolean> {
if (!sourceFiles.length) {
return Promise.resolve(false);
}
Expand Down Expand Up @@ -2545,7 +2545,7 @@ export class FolderActionsService {
});
}

private moveFileToFolder(file: File, targetFolderId: number, targetNodeId: number): Promise<void> {
private moveFileToFolder(file: CMSFile, targetFolderId: number, targetNodeId: number): Promise<void> {
const type = file.type;
this.appState.dispatch(new StartListSavingAction(type));

Expand Down Expand Up @@ -2651,7 +2651,7 @@ export class FolderActionsService {
* Uploads a file to the backend. If uploads are already in progress,
* the new files are added to the current upload state.
*/
uploadFiles(type: 'file' | 'image', files: any[], folderId: number): Observable<UploadResponse[]> {
uploadFiles(type: 'file' | 'image', files: File[], folderId: number): Observable<UploadResponse[]> {
if (type !== 'image' && type !== 'file') {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
console.error(`Can not upload ${type}.`);
Expand Down Expand Up @@ -2685,6 +2685,7 @@ export class FolderActionsService {
if (failed.length > 0) {
// If the server provides an error message, show it to the user.
const fileErrors = failed.map(res => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
const fileError = (res.error.data?.messages?.[0]?.message || res.error.message || '')
.replace(/\.$/, '');
return [
Expand Down Expand Up @@ -2712,7 +2713,7 @@ export class FolderActionsService {
if (completed.length > 0) {
// Because the dimensions of an Image can only be accessed async, we need to use promises for
// all entities. If the dimensions are assumed to be available, a race condition can result.
const entitiesLoader: Promise<File<Raw> | Image<Raw>>[] = completed.map(res => {
const entitiesLoader: Promise<CMSFile<Raw> | Image<Raw>>[] = completed.map(res => {
if (type !== 'image') {
return Promise.resolve(res.item);
}
Expand All @@ -2739,7 +2740,7 @@ export class FolderActionsService {
/**
* Uploads a file to replace an existing file.
*/
replaceFile(type: 'image' | 'file', fileId: number, file: any, fileName?: string, options?: FileReplaceOptions): Observable<UploadResponse> {
replaceFile(type: 'image' | 'file', fileId: number, file: File, fileName?: string, options?: FileReplaceOptions): Observable<UploadResponse> {
if (type !== 'image' && type !== 'file') {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
console.error(`Can not upload ${type}.`);
Expand Down Expand Up @@ -2886,7 +2887,7 @@ export class FolderActionsService {

return this.client.file.create(payload).pipe(
switchMap(uploadResponse => {
let loader: Observable<File | Image>;
let loader: Observable<CMSFile | Image>;

// Refetch uploaded to since response from `POST file/create` differs from default entity data.
if (type === 'file') {
Expand Down
2 changes: 1 addition & 1 deletion cms-ui/libs/cms-models/src/lib/models/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { DefaultModelType, ModelType, Normalizable, Raw } from './type-util';
* These are the user-editable properties of a File object.
*/
export type EditableFileProps = Partial<Pick<FileOrImage, 'name' | 'description' | 'forceOnline'
| 'niceUrl' | 'alternateUrls' | 'customCdate' | 'customEdate'>>;
| 'niceUrl' | 'alternateUrls' | 'customCdate' | 'customEdate' | 'tags'>>;

/**
* Superinterface for CMS files and images.
Expand Down
6 changes: 3 additions & 3 deletions cms-ui/libs/e2e-utils/src/lib/cypress-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,20 +423,20 @@ export function registerCommonCommands(): void {
});

Cypress.Commands.add('findTableRowContainingText', {prevSubject: 'element'}, (subject, text) => {
return cy.wrap(subject)
return cy.wrap(subject, { log: false })
.find('.grid-row')
.contains(text)
.parents('.grid-row');
});

Cypress.Commands.add('selectTableRow', {prevSubject: 'element'}, (subject) => {
return cy.wrap(subject)
return cy.wrap(subject, { log: false })
.find('gtx-checkbox.selection-checkbox')
.click();
});

Cypress.Commands.add('expandTrableRow', {prevSubject: 'element'}, (subject) => {
return cy.wrap(subject)
return cy.wrap(subject, { log: false })
.find('.row-expansion-wrapper')
.click();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
class="view-value select-input"
[attr.tabindex]="disabled ? null : 0"
[attr.disabled]="disabled ? true : null"
[attr.data-value]="valueArray"
[class.has-disabled-unknowns]="disableUnknownValues && unknownValues.length > 0"
data-context-trigger
(blur)="inputBlur($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export class SelectComponent
@ContentChildren(SelectOptionGroupDirective, { descendants: false })
private selectOptionGroups: QueryList<SelectOptionGroupDirective>;

private valueArray: (number | string)[] = [];
public valueArray: (number | string)[] = [];

// An array of abstracted containers for options, which allows us to treat options and groups in a
// consistent way.
Expand Down Expand Up @@ -173,7 +173,6 @@ export class SelectComponent
}
}


ngAfterViewInit(): void {
// Update the value if there are any changes to the options
this.subscriptions.push(this.selectOptions.changes.subscribe(() => {
Expand Down