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

[ACS-6456] Migrated Share File e2es to Playwright #3565

Merged
merged 5 commits into from
Dec 22, 2023
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
246 changes: 246 additions & 0 deletions e2e/playwright/actions/src/tests/share/share-file.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
/*!
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Alfresco Example Content Application
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/

import { ApiClientFactory, NodesApi, test, timeouts, Utils, SharedLinksApi } from '@alfresco/playwright-shared';
import { expect } from '@playwright/test';

test.describe('Share a file', () => {
const random = Utils.random();

const username = `user-${random}`;
const parent = `parent-${random}`;
let parentId: string;

const file3 = `file3-${random}.txt`;
const file4 = `file4-${random}.txt`;
const file5 = `file5-${random}.txt`;
const file6 = `file6-${random}.txt`;
const file7 = `file7-${random}.txt`;
const file8 = `file8-${random}.txt`;
const file9 = `file9-${random}.txt`;

const shareLinkPreUrl = `/#/preview/s/`;

const apiClientFactory = new ApiClientFactory();

test.beforeAll(async () => {
await apiClientFactory.setUpAcaBackend('admin');
await apiClientFactory.createUser({ username });
const nodesApi = await NodesApi.initialize(username, username);

parentId = (await nodesApi.createFolder(parent)).entry.id;
});

test.afterAll(async () => {
await apiClientFactory.nodes.deleteNodes([parentId]);
});

test.describe('when logged out', () => {
let file6SharedLink: string;
let file6Id: string;

test.beforeAll(async () => {
const nodesApi = await NodesApi.initialize(username, username);
const shareApi = await SharedLinksApi.initialize(username, username);

file6Id = (await nodesApi.createFile(file6, parentId))?.entry.id;

const sharedId = (await shareApi.shareFileById(file6Id)).entry.id;
file6SharedLink = `${shareLinkPreUrl}${sharedId}`;
await shareApi.waitForFilesToBeShared([file6Id]);
});

test.afterAll(async () => {
await apiClientFactory.nodes.deleteNodes([file6Id]);
});

test('[C286326] A non-logged user can download the shared file from the viewer', async ({ personalFiles, page }) => {
await page.goto(file6SharedLink);
await personalFiles.viewer.waitForViewerToOpen();

const downloadPromise = personalFiles.page.waitForEvent('download');
await personalFiles.viewer.toolbar.sharedDownloadButton.click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toBe(file6);
});
});

test.describe('when logged in', () => {
const expiryDateObj = new Date();
expiryDateObj.setFullYear(expiryDateObj.getFullYear() + 1);
const expiryDate: any = expiryDateObj.toISOString().replace('Z', '+0000');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use any

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing 'any' here is giving a red line error on expiryDate here
await shareApi.shareFilesByIds([file6Id, file7Id], expiryDate);
because shareFileByIds() and other nested methods expect expireDate to be of type 'Date'. But strangely, the shareFilesByIds() method works only if the expireDate is of type 'string', otherwise the tests don't work as expected.
image

Due to this strange behavior, having 'any' helps but if I remove 'any', I will have to modify the data type of expireDate from 'Date' to 'string' at multiple places and in JS-API which will need upstream.

I have tried multiple ways to make expiryDate an object of type 'Date' so that no changes are required on the API level but that does not seem to work

What do you suggest here? Should we go ahead with 'any'? or can we use some other approach here? @MichalKinas

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you need to pass a Date there you can use expiryDateObj object, expiryDate should be a string and using any here is incorrect

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tried using expiryDateObj but this does not help as 'shareFilesByIds()' is working properly only with expiryDate as string.
If we remove any, we get an error because 'shareFilesByIds()' expects a Date but is somehow working only with string

Copy link
Contributor

@MichalKinas MichalKinas Dec 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can try creating new date from expiryDate but if it won't work it means that your code is not correct somewhere, any is anti-pattern and it should be used only in specific cases and this is not one of them. any shouldn't be used to fix an error or not working code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I understand what you are saying but the problem I am facing in doing so is that

  1. the API actually expects 'expiryDate' to be of type string. (see sharedLinkBodyCreate https://api-explorer.alfresco.com/api-explorer/?urls.primaryName=Core%20API#/shared-links/createSharedLink)
    image

  2. But, in the code, the expected type of 'expiryDate' is set to Date in JS API and all related methods like 'shareNodes()' or 'shareFileByIds()'
    image

So even if I create new date from 'expiryDate' , the API will still not run as expected.
So far, this approach (using 'any') was being used in Protractor e2es so if we remove 'any', we either get some red line errors but the tests run fine
OR
we might need to make changes in JS API which I am not sure is feasible.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case you still don't have to use any, you can declare expiryDate as let expiryDate: Date | string = ... and then pass it to the correct function like expiryDate as Date

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing expiryDate as Date does not help because this.apiService.share.createSharedLink(data); fails if expiry is of type 'Date' and gives status code 400.
It gives 200 only with type string (as per swagger https://api-explorer.alfresco.com/api-explorer/?urls.primaryName=Core%20API#/shared-links/createSharedLink)
and I am blocked because I cannot set the type of expiryDate to string.
image (3)
image (2)

@DenysVuika, Michal suggested double-checking with you if we should make changes for this in JS-API for e2es.
Can you please suggest what would be the feasible solution?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MichalKinas, as per my discussion with @DenysVuika, we can use 'any' for now and have a separate ticket to fix typings in JS-API.

I have created this JIRA https://alfresco.atlassian.net/browse/ACS-6533 for the same.


test.describe('from Personal Files', () => {
let file3Id: string;
let file4Id: string;
let file5Id: string;
let file6Id: string;
let file7Id: string;
let file8Id: string;
let file9Id: string;

test.beforeAll(async () => {
test.setTimeout(timeouts.extendedTest);
const nodesApi = await NodesApi.initialize(username, username);
const shareApi = await SharedLinksApi.initialize(username, username);

file3Id = (await nodesApi.createFile(file3, parentId))?.entry.id;
file4Id = (await nodesApi.createFile(file4, parentId))?.entry.id;
file5Id = (await nodesApi.createFile(file5, parentId))?.entry.id;
file6Id = (await nodesApi.createFile(file6, parentId))?.entry.id;
file7Id = (await nodesApi.createFile(file7, parentId))?.entry.id;
file8Id = (await nodesApi.createFile(file8, parentId))?.entry.id;
file9Id = (await nodesApi.createFile(file9, parentId))?.entry.id;

await shareApi.shareFilesByIds([file6Id, file7Id], expiryDate);
await shareApi.waitForFilesToBeShared([file6Id, file7Id]);
});

test.beforeEach(async ({ loginPage, personalFiles, page }) => {
await loginPage.navigate();
await loginPage.loginUser({ username: username, password: username });

await personalFiles.waitForPageLoad();
await personalFiles.dataTable.getCellByColumnNameAndRowItem(parent, 'Size').dblclick();
await page.waitForTimeout(timeouts.tiny);
});

test.afterAll(async () => {
const nodesApi = await NodesApi.initialize(username, username);
await nodesApi.deleteNodes([file3Id, file4Id, file5Id, file6Id, file7Id, file8Id, file9Id]);
});

test('[C286327] Share dialog default values', async ({ personalFiles }) => {
expect(await personalFiles.dataTable.performActionFromExpandableMenu(file3, 'Share'));
const labels = await personalFiles.shareDialog.getLabels();
expect(await personalFiles.shareDialog.getDialogTitle()).toEqual(`Share ${file3}`);
expect(labels[0].trim()).toBe(`Share ${file3}`);
expect(await personalFiles.shareDialog.getInfoText()).toEqual('Share Link');
expect(await personalFiles.shareDialog.getLinkUrl()).toContain(shareLinkPreUrl);
expect(await personalFiles.shareDialog.isUrlReadOnly()).toBe(true);
expect(await personalFiles.shareDialog.isShareToggleChecked()).toBe(true);
expect(labels[1].trim()).toBe('Link Expiry Date');
expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(false);
expect(await personalFiles.shareDialog.isCloseEnabled()).toBe(true);
});

test('[C286329] Share a file', async ({ personalFiles, nodesApiAction }) => {
expect(await personalFiles.dataTable.performActionFromExpandableMenu(file3, 'Share'));

const url = await personalFiles.shareDialog.getLinkUrl();
await personalFiles.shareDialog.clickClose();

const sharedId = await nodesApiAction.getSharedId(file3Id);
expect(url).toContain(sharedId);
});

test('[C286330] Copy shared file URL', async ({ personalFiles, page }) => {
expect(await personalFiles.dataTable.performActionFromExpandableMenu(file4, 'Share'));

const url = await personalFiles.shareDialog.getLinkUrl();
expect(url).toContain(shareLinkPreUrl);

await personalFiles.shareDialog.urlAction.click();

const shareSnackBar = personalFiles.snackBar;
await expect(shareSnackBar.getByMessageLocator('Link copied to the clipboard')).toBeVisible();

await page.goto(url);
akashrathod28 marked this conversation as resolved.
Show resolved Hide resolved
await personalFiles.viewer.waitForViewerToOpen();

const downloadPromise = personalFiles.page.waitForEvent('download');
await personalFiles.viewer.toolbar.sharedDownloadButton.click();

const download = await downloadPromise;
expect(download.suggestedFilename()).toBe(file4);
});

test('[C286332] Share a file with expiration date', async ({ personalFiles, nodesApiAction, page }) => {
expect(await personalFiles.dataTable.performActionFromExpandableMenu(file5, 'Share'));

await personalFiles.shareDialog.expireToggle.click();
expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(true);

await personalFiles.shareDialog.datetimePickerButton.click();
expect(await personalFiles.shareDialog.dateTimePicker.isCalendarOpen()).toBe(true);

await personalFiles.shareDialog.dateTimePicker.pickDateTime();

const inputDate = await personalFiles.shareDialog.getExpireDate();

await page.waitForTimeout(timeouts.normal);
akashrathod28 marked this conversation as resolved.
Show resolved Hide resolved
const expireDateProperty = await nodesApiAction.getSharedExpiryDate(file5Id);

expect(Utils.formatDate(expireDateProperty)).toEqual(Utils.formatDate(inputDate));
});

test('[C286337] Expire date is displayed correctly', async ({ personalFiles, nodesApiAction }) => {
expect(await personalFiles.dataTable.performActionFromExpandableMenu(file6, 'Share'));
const expireProperty = await nodesApiAction.getSharedExpiryDate(file6Id);

expect(expireProperty).toEqual(expiryDate);
expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(true);
expect(Utils.formatDate(await personalFiles.shareDialog.getExpireDate())).toEqual(Utils.formatDate(expiryDate));
});

test('[C286333] Disable the share link expiration', async ({ personalFiles, nodesApiAction, page }) => {
expect(await personalFiles.dataTable.performActionFromExpandableMenu(file7, 'Share'));

expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(true);
expect(await personalFiles.shareDialog.getExpireDate()).not.toBe('');

await personalFiles.shareDialog.expireToggle.click();
expect(await personalFiles.shareDialog.isExpireToggleEnabled()).toBe(false);

await page.waitForTimeout(timeouts.tiny);
await personalFiles.shareDialog.clickClose();
expect(await nodesApiAction.getSharedExpiryDate(file7Id)).toBe('');
});

test('[C286335] Shared file URL is not changed when Share dialog is closed and opened again', async ({ personalFiles }) => {
expect(await personalFiles.dataTable.performActionFromExpandableMenu(file8, 'Share'));

const url1 = await personalFiles.shareDialog.getLinkUrl();
await personalFiles.shareDialog.clickClose();

await personalFiles.dataTable.selectItem(file8);
await personalFiles.acaHeader.shareButton.click();
const url2 = await personalFiles.shareDialog.getLinkUrl();

expect(url1).toEqual(url2);
});

test('[C286345] Share a file from the context menu', async ({ personalFiles, nodesApiAction }) => {
expect(await personalFiles.dataTable.performActionFromExpandableMenu(file9, 'Share'));

const url = await personalFiles.shareDialog.getLinkUrl();
await personalFiles.shareDialog.clickClose();

const sharedId = await nodesApiAction.getSharedId(file9Id);
expect(await nodesApiAction.isFileShared(file9Id)).toBe(true);
expect(url).toContain(sharedId);
});
});
});
});
Loading
Loading