Skip to content

Commit

Permalink
feat(quantic): quantic user actions session component created (#4473)
Browse files Browse the repository at this point in the history
## [SFINT-5678](https://coveord.atlassian.net/browse/SFINT-5678)

### Quantic User Actions Session component created

The `QuanticUserActionsSession` component displays all the user actions
that took place during a specific user session.
This component will be used by the Quantic User Actions Timeline
component that displayed the whole timeline containing two following
sessions and two preceding sessions and the ticket creation session,

## Demo



https://github.com/user-attachments/assets/ba289093-f8b8-494c-bc9e-a4f54dd80c9e



#### Link to mockups:
https://www.figma.com/design/tc1NDbxceu3tW1UjFIt8cm/Salesforce%3A-Quantic-Insight-Panel?node-id=204-13558&t=FtqdEiwgSTdxArJZ-0

[SFINT-5678]:
https://coveord.atlassian.net/browse/SFINT-5678?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

---------

Co-authored-by: Simon Milord <[email protected]>
  • Loading branch information
mmitiche and SimonMilord authored Sep 30, 2024
1 parent 7add130 commit 0882dbc
Show file tree
Hide file tree
Showing 7 changed files with 452 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1540,4 +1540,18 @@
<protected>false</protected>
<shortDescription>Empty search</shortDescription>
</labels>
<labels>
<fullName>quantic_MoreActionsInThisSession</fullName>
<value>{{0}} more action in this session</value>
<language>en_US</language>
<protected>false</protected>
<shortDescription>1 more action in this session</shortDescription>
</labels>
<labels>
<fullName>quantic_MoreActionsInThisSession_plural</fullName>
<value>{{0}} more actions in this session</value>
<language>en_US</language>
<protected>false</protected>
<shortDescription>12 more actions in this session</shortDescription>
</labels>
</CustomLabels>
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
// @ts-ignore
import quanticUserActionsSession from 'c/quanticUserActionsSession';
// @ts-ignore
import {createElement} from 'lwc';

const selectors = {
sessionDateIcon: '[data-test="session-start__date-icon"]',
sessionDate: '[data-test="session-start__date"]',
showMoreActions: '[data-test="session__show-more-actions-button"]',
userActions: '[data-test="session__user-actions"] c-quantic-user-action',
userActionsAferTicketCreation:
'[data-test="session__user-actions-after-ticket-creation"] c-quantic-user-action',
};

function createTestComponent(options) {
const element = createElement('c-quantic-user-actions-session', {
is: quanticUserActionsSession,
});
for (const [key, value] of Object.entries(options)) {
element[key] = value;
}

document.body.appendChild(element);
return element;
}

// Helper function to wait until the microtask queue is empty.
function flushPromises() {
// eslint-disable-next-line @lwc/lwc/no-async-operation
return new Promise((resolve) => setTimeout(resolve, 0));
}

describe('c-quantic-user-actions-session', () => {
function cleanup() {
// The jsdom instance is shared across test cases in a single file so reset the DOM
while (document.body.firstChild) {
document.body.removeChild(document.body.firstChild);
}
jest.clearAllMocks();
}

afterEach(() => {
cleanup();
});

describe('when the user action session does not contain a ticket creation action', () => {
const exampleActions = [
{
actionType: 'SEARCH',
timestamp: new Date('2024-09-25T05:08Z').getTime(),
query: 'example query',
},
{
actionType: 'SEARCH',
timestamp: new Date('2024-09-25T05:07Z').getTime(),
query: 'example query',
},
];

describe('the session start date', () => {
it('should display the session start date without the icon', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

const sessionDateIcon = element.shadowRoot.querySelector(
selectors.sessionDateIcon
);
const sessionDate = element.shadowRoot.querySelector(
selectors.sessionDate
);

expect(sessionDateIcon).toBeNull();
expect(sessionDate).not.toBeNull();

expect(sessionDate.textContent).toBe('Wed. September 25, 2024');
});
});

describe('the show more actions button', () => {
it('should not show the show more actions button', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

const showMoreActions = element.shadowRoot.querySelector(
selectors.showMoreActions
);

expect(showMoreActions).toBeNull();
});
});

describe('the session user actions', () => {
it('should properly display the user actions', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

const userActions = element.shadowRoot.querySelectorAll(
selectors.userActions
);

expect(userActions.length).toBe(exampleActions.length);
for (let index = 0; index < exampleActions.length; index++) {
expect(userActions[index].action).toEqual(exampleActions[index]);
}
});
});
});

describe('when the user action session contains a ticket creation action', () => {
const exampleActions = [
{
actionType: 'SEARCH',
timestamp: new Date('2024-09-25T05:09Z').getTime(),
query: 'example query',
},
{
actionType: 'TICKET_CREATION',
timestamp: new Date('2024-09-25T05:08Z').getTime(),
},
{
actionType: 'SEARCH',
timestamp: new Date('2024-09-25T05:07Z').getTime(),
query: 'example query',
},
];
const numberOfActionsAfterTicketCreation = 1;

describe('the session start date', () => {
it('should display the session start date with the icon', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

const sessionDateIcon = element.shadowRoot.querySelector(
selectors.sessionDateIcon
);
const sessionDate = element.shadowRoot.querySelector(
selectors.sessionDate
);

expect(sessionDateIcon).not.toBeNull();
expect(sessionDate).not.toBeNull();

expect(sessionDate.textContent).toBe('Wed. September 25, 2024');
});
});

describe('the session user actions', () => {
it('should display the user actions that occurred before the ticket creation', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

const userActions = element.shadowRoot.querySelectorAll(
selectors.userActions
);

expect(userActions.length).toBe(
exampleActions.length - numberOfActionsAfterTicketCreation
);
for (
let index = numberOfActionsAfterTicketCreation;
index < exampleActions.length;
index++
) {
expect(userActions[index - 1].action).toEqual(exampleActions[index]);
}
});

it('should not display the user actions that occurred after the ticket creation', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

const userActions = element.shadowRoot.querySelectorAll(
selectors.userActionsAferTicketCreation
);

expect(userActions.length).toBe(0);
});

describe('after clicking the show more actions button', () => {
it('should display the user actions that occurred after the ticket creation', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

const showMoreActions = element.shadowRoot.querySelector(
selectors.showMoreActions
);

showMoreActions.click();
await flushPromises();

const userActionsAferTicketCreation =
element.shadowRoot.querySelectorAll(
selectors.userActionsAferTicketCreation
);

expect(userActionsAferTicketCreation.length).toBe(
numberOfActionsAfterTicketCreation
);
for (
let index = 0;
index < numberOfActionsAfterTicketCreation;
index++
) {
expect(userActionsAferTicketCreation[index].action).toEqual(
exampleActions[index]
);
}
});
});
});

describe('the show more actions button', () => {
it('should display the show more actions button', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

const showMoreActions = element.shadowRoot.querySelector(
selectors.showMoreActions
);

expect(showMoreActions).not.toBeNull();
});

it('should hide the show more actions button after clicking on it', async () => {
const element = createTestComponent({
userActions: exampleActions,
startTimestamp: new Date('2024-09-25T05:07Z'),
});
await flushPromises();

let showMoreActions = element.shadowRoot.querySelector(
selectors.showMoreActions
);

showMoreActions.click();
await flushPromises();

showMoreActions = element.shadowRoot.querySelector(
selectors.showMoreActions
);
expect(showMoreActions).toBeNull();
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.items-center {
align-items: center;
}

.session-start__icon-container {
background-color: orange;
border-radius: var(--lwc-borderRadiusCircle, 50%);
width: 24px;
height: 24px;
}

.session__show-more-actions-button {
font-size: 12px;
}

.session-start__icon {
--slds-c-icon-color-foreground-default: white;
}

.session-start__date {
font-style: italic;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<div class="slds-grid items-center slds-var-m-bottom_xx-small">
<template lwc:if={isTicketCreationSession}>
<div data-test="session-start__date-icon"
class="session-start__icon-container slds-grid slds-grid_align-center slds-var-m-right_x-small items-center">
<lightning-icon class='session-start__icon' icon-name='utility:priority'
size="xx-small"></lightning-icon>
</div>
</template>
<div data-test="session-start__date" class="session-start__date slds-text-title_bold">{formatedStartDate}</div>
</div>

<template lwc:if={areActionsAfterTicketCreationVisible}>
<div data-test="session__user-actions-after-ticket-creation" class="slds-var-p-horizontal_xx-smalls">
<template for:each={userActionsAfterTicketCreation} for:item="action">
<div key={action.timestamp}>
<c-quantic-user-action action={action}></c-quantic-user-action>
</div>
</template>
</div>
</template>

<template lwc:if={isShowMoreActionsButtonVisible}>
<div class="slds-var-p-horizontal_xx-smalls">
<lightning-button data-test="session__show-more-actions-button" class="session__show-more-actions-button"
variant="base" label={showMoreActionsButtonLabel} title={showMoreActionsButtonLabel}
onclick={showActionsAfterTicketCreation} icon-name="utility:threedots"></lightning-button>
</div>
</template>


<div data-test="session__user-actions" class="slds-var-p-horizontal_xx-smalls">
<template for:each={userActionsToDisplay} for:item="action">
<div key={action.timestamp}>
<c-quantic-user-action action={action}></c-quantic-user-action>
</div>
</template>
</div>

</template>
Loading

0 comments on commit 0882dbc

Please sign in to comment.