Skip to content

Commit

Permalink
[FIX] Save edited tags for omnichannel departments (#26481)
Browse files Browse the repository at this point in the history
Co-authored-by: Aleksander Nicacio da Silva <6494543+aleksandernsilva@users.noreply.github.com>
Co-authored-by: Guilherme Gazzo <5263975+ggazzo@users.noreply.github.com>
  • Loading branch information
3 people authored and csuarez committed Aug 26, 2022
1 parent fb3494b commit 6a59a8a
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 37 deletions.
7 changes: 6 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,10 @@
}
],
"typescript.tsdk": "./node_modules/typescript/lib",
"cSpell.words": ["photoswipe", "tmid"]
"cSpell.words": [
"livechat",
"omnichannel",
"photoswipe",
"tmid"
]
}
24 changes: 18 additions & 6 deletions apps/meteor/client/views/omnichannel/departments/EditDepartment.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@rocket.chat/fuselage';
import { useMutableCallback, useUniqueId } from '@rocket.chat/fuselage-hooks';
import { useToastMessageDispatch, useRoute, useMethod, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts';
import React, { useMemo, useState, useRef } from 'react';
import React, { useMemo, useState, useRef, useCallback } from 'react';

import { validateEmail } from '../../../../lib/emailValidator';
import Page from '../../../components/Page';
Expand Down Expand Up @@ -58,7 +58,9 @@ function EditDepartment({ data, id, title, reload, allowedToForwardData }) {

const { department } = data || { department: {} };

const [[tags, tagsText], setTagsState] = useState(() => [department?.chatClosingTags ?? [], '']);
const [initialTags] = useState(() => department?.chatClosingTags ?? []);
const [[tags, tagsText], setTagsState] = useState(() => [initialTags, '']);
const hasTagChanges = useMemo(() => tags.toString() !== initialTags.toString(), [tags, initialTags]);

const { values, handlers, hasUnsavedChanges } = useForm({
name: withDefault(department?.name, ''),
Expand Down Expand Up @@ -120,7 +122,7 @@ function EditDepartment({ data, id, title, reload, allowedToForwardData }) {
setTagsState(([tags, tagsText]) => [tags.filter((_tag) => _tag !== tag), tagsText]);
};

const handleTagTextSubmit = useMutableCallback(() => {
const handleTagTextSubmit = useCallback(() => {
setTagsState((state) => {
const [tags, tagsText] = state;

Expand All @@ -130,7 +132,7 @@ function EditDepartment({ data, id, title, reload, allowedToForwardData }) {

return [[...tags, tagsText], ''];
});
});
}, []);

const handleTagTextChange = (e) => {
setTagsState(([tags]) => [tags, e.target.value]);
Expand Down Expand Up @@ -232,7 +234,11 @@ function EditDepartment({ data, id, title, reload, allowedToForwardData }) {
});

const invalidForm =
!name || !email || !validateEmail(email) || !hasUnsavedChanges || (requestTagBeforeClosingChat && (!tags || tags.length === 0));
!name ||
!email ||
!validateEmail(email) ||
!(hasUnsavedChanges || hasTagChanges) ||
(requestTagBeforeClosingChat && (!tags || tags.length === 0));

const formId = useUniqueId();

Expand Down Expand Up @@ -441,7 +447,13 @@ function EditDepartment({ data, id, title, reload, allowedToForwardData }) {
onChange={handleTagTextChange}
placeholder={t('Enter_a_tag')}
/>
<Button mis='x8' title={t('add')} onClick={handleTagTextSubmit}>
<Button
disabled={Boolean(!tagsText.trim()) || tags.includes(tagsText)}
data-qa='DepartmentEditAddButton-ConversationClosingTags'
mis='x8'
title={t('add')}
onClick={handleTagTextSubmit}
>
{t('Add')}
</Button>
</Field.Row>
Expand Down
126 changes: 99 additions & 27 deletions apps/meteor/tests/e2e/omnichannel-departaments.spec.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,123 @@
import { faker } from '@faker-js/faker';
import type { Page } from '@playwright/test';

import { test, expect } from './utils/test';
import { OmnichannelDepartaments } from './page-objects';
import { OmnichannelDepartments } from './page-objects';

test.use({ storageState: 'admin-session.json' });

test.describe.serial('omnichannel-departaments', () => {
let poOmnichannelDepartaments: OmnichannelDepartaments;
test.describe.serial('omnichannel-departments', () => {
let poOmnichannelDepartments: OmnichannelDepartments;

const departmentName = faker.datatype.uuid();
let departmentName: string;
test.beforeAll(() => {
departmentName = faker.datatype.uuid();
});

test.beforeEach(async ({ page }) => {
poOmnichannelDepartaments = new OmnichannelDepartaments(page);
test.beforeEach(async ({ page }: { page: Page }) => {
poOmnichannelDepartments = new OmnichannelDepartments(page);

await page.goto('/omnichannel');
await poOmnichannelDepartaments.sidenav.linkDepartments.click();
await poOmnichannelDepartments.sidenav.linkDepartments.click();
});

test('expect create new department', async () => {
await poOmnichannelDepartaments.btnNew.click();
await poOmnichannelDepartaments.btnEnabled.click();
await poOmnichannelDepartaments.inputName.fill(departmentName);
await poOmnichannelDepartaments.inputEmail.fill(faker.internet.email());
await poOmnichannelDepartaments.btnSave.click();

await poOmnichannelDepartaments.inputSearch.fill(departmentName);
await expect(poOmnichannelDepartaments.firstRowInTable).toBeVisible();
await poOmnichannelDepartments.btnNew.click();
await poOmnichannelDepartments.btnEnabled.click();
await poOmnichannelDepartments.inputName.fill(departmentName);
await poOmnichannelDepartments.inputEmail.fill(faker.internet.email());
await poOmnichannelDepartments.btnSave.click();

await poOmnichannelDepartments.inputSearch.fill(departmentName);
await expect(poOmnichannelDepartments.firstRowInTable).toBeVisible();
});

test('expect update department name', async () => {
await poOmnichannelDepartaments.inputSearch.fill(departmentName);
await poOmnichannelDepartments.inputSearch.fill(departmentName);

await poOmnichannelDepartments.firstRowInTable.locator(`text=${departmentName}`).click();
await poOmnichannelDepartments.inputName.fill(`edited-${departmentName}`);
await poOmnichannelDepartments.btnSave.click();

await poOmnichannelDepartments.inputSearch.fill(`edited-${departmentName}`);
await expect(poOmnichannelDepartments.firstRowInTable).toBeVisible();
});

test.describe('Tags', () => {
test.beforeEach(async () => {
await poOmnichannelDepartments.inputSearch.fill(departmentName);
await poOmnichannelDepartments.firstRowInTable.locator(`text=${departmentName}`).click();
});

test('expect save form button be disabled', async () => {
await expect(poOmnichannelDepartments.btnSave).toBeDisabled();
});

test('Disabled tags state', async () => {
await test.step('expect to have department tags toggle button', async () => {
await expect(poOmnichannelDepartments.toggleRequestTags).toBeVisible();
});
await test.step('expect have no add tag to department', async () => {
await expect(poOmnichannelDepartments.inputTags).not.toBeVisible();
await expect(poOmnichannelDepartments.btnTagsAdd).not.toBeVisible();
});
});

await poOmnichannelDepartaments.firstRowInTable.locator(`text=${departmentName}`).click();
await poOmnichannelDepartaments.inputName.fill(`edited-${departmentName}`);
await poOmnichannelDepartaments.btnSave.click();
test('Enabled tags state', async ({ page }) => {
await test.step('expect to have form save option disabled', async () => {
await expect(poOmnichannelDepartments.btnSave).toBeDisabled();
});

await poOmnichannelDepartaments.inputSearch.fill(`edited-${departmentName}`);
await expect(poOmnichannelDepartaments.firstRowInTable).toBeVisible();
await test.step('expect clicking on toggle button to enable tags', async () => {
await poOmnichannelDepartments.toggleRequestTags.click();
await expect(poOmnichannelDepartments.inputTags).toBeVisible();
await expect(poOmnichannelDepartments.btnTagsAdd).toBeVisible();
});
await test.step('expect to be invalid if there is no tag added', async () => {
await expect(poOmnichannelDepartments.btnSave).toBeDisabled();
await expect(poOmnichannelDepartments.invalidInputTags).toBeVisible();
});

await test.step('expect to be not possible adding empty tags', async () => {
await poOmnichannelDepartments.inputTags.fill('');
await expect(poOmnichannelDepartments.btnTagsAdd).toBeDisabled();
});

await test.step('expect to have add and remove one tag properly tags', async () => {
const tagName = faker.datatype.string(5);
await poOmnichannelDepartments.inputTags.fill(tagName);
await poOmnichannelDepartments.btnTagsAdd.click();

await expect(page.locator(`button`, { hasText: tagName })).toBeVisible();

await expect(poOmnichannelDepartments.btnSave).toBeEnabled();

await page.locator(`button`, { hasText: tagName }).click();
await expect(poOmnichannelDepartments.invalidInputTags).toBeVisible();
await expect(poOmnichannelDepartments.btnSave).toBeDisabled();
});
await test.step('expect to not be possible adding same tag twice', async () => {
const tagName = faker.datatype.string(5);
await poOmnichannelDepartments.inputTags.fill(tagName);
await poOmnichannelDepartments.btnTagsAdd.click();
await poOmnichannelDepartments.inputTags.fill(tagName);
await expect(poOmnichannelDepartments.btnTagsAdd).toBeDisabled();
});
});
});

test('expect delete department', async () => {
await poOmnichannelDepartaments.inputSearch.fill(`edited-${departmentName}`);
test('expect delete department', async ({ page }) => {
await expect(poOmnichannelDepartments.firstRowInTable).toBeVisible();

await poOmnichannelDepartments.inputSearch.fill(`edited-${departmentName}`);

await page.waitForRequest('**/livechat/department**');

await poOmnichannelDepartments.btnDeleteFirstRowInTable.click();
await poOmnichannelDepartments.btnModalConfirmDelete.click();

await poOmnichannelDepartaments.btnDeletefirstRowInTable.click();
await poOmnichannelDepartaments.btnModalConfirmDelete.click();
await poOmnichannelDepartments.inputSearch.fill(`edited-${departmentName}`);

await poOmnichannelDepartaments.inputSearch.fill(`edited-${departmentName}`);
await expect(poOmnichannelDepartaments.firstRowInTable).toBeHidden();
await expect(poOmnichannelDepartments.firstRowInTable).toHaveCount(0);
});
});
2 changes: 1 addition & 1 deletion apps/meteor/tests/e2e/page-objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ export * from './auth';
export * from './home-channel';
export * from './home-discussion';
export * from './omnichannel-agents';
export * from './omnichannel-departaments';
export * from './omnichannel-departments';
export * from './omnichannel-livechat';
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Page } from '@playwright/test';

import { OmnichannelSidenav } from './fragments';

export class OmnichannelDepartaments {
export class OmnichannelDepartments {
private readonly page: Page;

readonly sidenav: OmnichannelSidenav;
Expand Down Expand Up @@ -32,6 +32,22 @@ export class OmnichannelDepartaments {
return this.page.locator('[data-qa="DepartmentEditTextInput-Email"]');
}

get toggleRequestTags() {
return this.page.locator('[data-qa="DiscussionToggle-RequestTagBeforeCLosingChat"] span label');
}

get inputTags() {
return this.page.locator('[data-qa="DepartmentEditTextInput-ConversationClosingTags"]');
}

get invalidInputTags() {
return this.page.locator('[data-qa="DepartmentEditTextInput-ConversationClosingTags"]:invalid');
}

get btnTagsAdd() {
return this.page.locator('[data-qa="DepartmentEditAddButton-ConversationClosingTags"]');
}

get btnSave() {
return this.page.locator('button.rcx-button--primary.rcx-button >> text="Save"');
}
Expand All @@ -40,7 +56,7 @@ export class OmnichannelDepartaments {
return this.page.locator('table tr:first-child td:first-child');
}

get btnDeletefirstRowInTable() {
get btnDeleteFirstRowInTable() {
return this.page.locator('table tr:first-child td:nth-child(6) button');
}

Expand Down

0 comments on commit 6a59a8a

Please sign in to comment.