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

feat: file list composite and breadcrumb #2560

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
10 changes: 6 additions & 4 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ <h1>Developer test page</h1>
<main>
<h2>mgt-login</h2>
<mgt-login login-view="compact"></mgt-login>
<mgt-login></mgt-login>
<!-- <mgt-login></mgt-login>
<h2>mgt-person me query two lines card on click with presence</h2>
<mgt-person person-query="me" view="twoLines" person-card="click" show-presence></mgt-person>
<h2>mgt-people-picker</h2>
Expand All @@ -88,9 +88,11 @@ <h2>mgt-people show-presence</h2>
<h2>mgt-todo</h2>
<mgt-todo></mgt-todo>
<h2>mgt-file-list</h2>
<mgt-file-list></mgt-file-list>
<h2>mgt-picker</h2>
<mgt-picker resource="me/todo/lists" scopes="tasks.read, tasks.readwrite"></mgt-picker>
<mgt-file-list></mgt-file-list> -->
<h2>mgt-file-composite</h2>
<mgt-file-composite breadcrumb-root-name="Drive"></mgt-file-composite>
<!-- <h2>mgt-picker</h2>
<mgt-picker resource="me/todo/lists" scopes="tasks.read, tasks.readwrite"></mgt-picker> -->
</main>
</body>
</html>
2 changes: 1 addition & 1 deletion packages/mgt-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@microsoft/microsoft-graph-client": "^3.0.0",
"@microsoft/microsoft-graph-types": "^2.0.0",
"@microsoft/microsoft-graph-types-beta": "^0.16.0-preview",
"@fluentui/web-components": "^2.5.3",
"@fluentui/web-components": "^2.5.12",
"office-ui-fabric-core": "^11.0.0"
},
"publishConfig": {
Expand Down
20 changes: 20 additions & 0 deletions packages/mgt-components/src/__mocks__/mock-media-match.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation(query => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn()
}))
});
4 changes: 4 additions & 0 deletions packages/mgt-components/src/components/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ import './mgt-person/mgt-person-types';
import './mgt-tasks/mgt-tasks';
import './mgt-teams-channel-picker/mgt-teams-channel-picker';
import './mgt-todo/mgt-todo';
import './mgt-breadcrumb/mgt-breadcrumb';
import './mgt-contact/mgt-contact';
import './mgt-messages/mgt-messages';
import './mgt-organization/mgt-organization';
import './mgt-profile/mgt-profile';
import './mgt-theme-toggle/mgt-theme-toggle';
import './mgt-file-composite/mgt-file-composite';

export * from './mgt-agenda/mgt-agenda';
export * from './mgt-file/mgt-file';
Expand All @@ -39,9 +41,11 @@ export * from './mgt-person/mgt-person-types';
export * from './mgt-tasks/mgt-tasks';
export * from './mgt-teams-channel-picker/mgt-teams-channel-picker';
export * from './mgt-todo/mgt-todo';
export * from './mgt-breadcrumb/mgt-breadcrumb';
export * from './mgt-contact/mgt-contact';
export * from './mgt-contact/mgt-contact';
export * from './mgt-messages/mgt-messages';
export * from './mgt-organization/mgt-organization';
export * from './mgt-profile/mgt-profile';
export * from './mgt-theme-toggle/mgt-theme-toggle';
export * from './mgt-file-composite/mgt-file-composite';
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

@import '../../../../../node_modules/office-ui-fabric-core/dist/sass/References';
@import '../../styles/shared-styles.scss';
@import './mgt-breadcrumb.theme.scss';

:host {
--type-ramp-base-font-size: var(--breadcrumb-base-font-size, 18px);
--type-ramp-base-line-height: var(--breadcrumb-base-line-height, 36px);

&::part(crumb),
&::part(control) {
padding: 0 calc((10 + (var(--design-unit) * 2 * var(--density))) * 1px);
}

&::part(crumb) {
font-weight: 600;
}
&::part(control) {
background-color: var(--neutral-fill-rest);
background: var(--neutral-fill-rest);
padding: 0 calc((10 + (var(--design-unit) * 2 * var(--density))) * 1px);
&:hover {
background-color: var(--neutral-fill-stealth-hover);
background: var(--neutral-fill-stealth-hover);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
import '../../__mocks__/mock-media-match';
import { screen } from 'testing-library__dom';
import userEvent from '@testing-library/user-event';
import { fixture } from '@open-wc/testing-helpers';
import './mgt-breadcrumb';
import { BreadcrumbInfo, MgtBreadcrumb } from './mgt-breadcrumb';

describe('mgt-breadcrumb - tests', () => {
it('should render', async () => {
const component = await fixture(`
<mgt-breadcrumb></mgt-breadcrumb>
`);
expect(component).toBeDefined();
});
it('should render with a single node', async () => {
const component: MgtBreadcrumb = await fixture(`
<mgt-breadcrumb></mgt-breadcrumb>
`);
component.breadcrumb = [
{
id: 'root-item',
name: 'root-item'
}
];
await component.updateComplete;
const listItems = await screen.findAllByRole('listitem');
expect(listItems?.length).toBe(1);
const root = await screen.findByText('root-item');
expect(root).toBeDefined();
});
it('should render with three nodes', async () => {
const component: MgtBreadcrumb = await fixture(`
<mgt-breadcrumb></mgt-breadcrumb>
`);
component.breadcrumb = [
{
id: '0',
name: 'root-item'
},
{
id: '1',
name: 'node-1'
},
{
id: '2',
name: 'node-2'
}
];
await component.updateComplete;
const listItems = await screen.findAllByRole('listitem');
expect(listItems?.length).toBe(3);
const root = await screen.findByText('root-item');
expect(root).toBeDefined();

const buttons = await screen.findAllByRole('button');

expect(buttons?.length).toBe(2);
});

it('should emit a clicked event when a button is clicked', async () => {
const component: MgtBreadcrumb = await fixture(`
<mgt-breadcrumb></mgt-breadcrumb>
`);
let eventEmitted;
component.addEventListener('breadcrumbclick', (e: CustomEvent<BreadcrumbInfo>) => {
eventEmitted = e.detail;
});

const rootNode = {
id: '0',
name: 'root-item'
};
component.breadcrumb = [
rootNode,
{
id: '1',
name: 'node-1'
}
];
await component.updateComplete;

const buttons = await screen.findAllByRole('button');
expect(buttons?.length).toBe(1);

buttons[0].click();
expect(eventEmitted).toBeDefined();
expect(eventEmitted).toBe(rootNode);
});

it('should emit a clicked event when the enter button is pressed', async () => {
const user = userEvent.setup();
const component: MgtBreadcrumb = await fixture(`
<mgt-breadcrumb></mgt-breadcrumb>
`);
let eventEmitted;
component.addEventListener('breadcrumbclick', (e: CustomEvent<BreadcrumbInfo>) => {
eventEmitted = e.detail;
});

const rootNode = {
id: '0',
name: 'root-item'
};
component.breadcrumb = [
rootNode,
{
id: '1',
name: 'node-1'
}
];
await component.updateComplete;

const buttons = await screen.findAllByRole('button');
expect(buttons?.length).toBe(1);
buttons[0].focus();

await user.keyboard('{Enter}');
expect(eventEmitted).toBeDefined();
expect(eventEmitted).toBe(rootNode);
});

it('should emit a clicked event when the space button is pressed', async () => {
const user = userEvent.setup();
const component: MgtBreadcrumb = await fixture(`
<mgt-breadcrumb></mgt-breadcrumb>
`);
let eventEmitted;
component.addEventListener('breadcrumbclick', (e: CustomEvent<BreadcrumbInfo>) => {
eventEmitted = e.detail;
});

const rootNode = {
id: '0',
name: 'root-item'
};
component.breadcrumb = [
rootNode,
{
id: '1',
name: 'node-1'
}
];
await component.updateComplete;

const buttons = await screen.findAllByRole('button');
expect(buttons?.length).toBe(1);
buttons[0].focus();

await user.keyboard(' ');
expect(eventEmitted).toBeDefined();
expect(eventEmitted).toBe(rootNode);
});

it('should not emit a clicked event when a regular character button is pressed', async () => {
const user = userEvent.setup();
const component: MgtBreadcrumb = await fixture(`
<mgt-breadcrumb></mgt-breadcrumb>
`);
let eventEmitted;
component.addEventListener('breadcrumbclick', (e: CustomEvent<BreadcrumbInfo>) => {
eventEmitted = e.detail;
});

const rootNode = {
id: '0',
name: 'root-item'
};
component.breadcrumb = [
rootNode,
{
id: '1',
name: 'node-1'
}
];
await component.updateComplete;

const buttons = await screen.findAllByRole('button');
expect(buttons?.length).toBe(1);
buttons[0].focus();

await user.keyboard('r');
expect(eventEmitted).toBeUndefined();
});

it('should not emit a clicked event when the last node is clicked', async () => {
const component: MgtBreadcrumb = await fixture(`
<mgt-breadcrumb></mgt-breadcrumb>
`);
let eventEmitted;
component.addEventListener('breadcrumbclick', (e: CustomEvent<BreadcrumbInfo>) => {
eventEmitted = e.detail;
});

const rootNode = {
id: '0',
name: 'root-item'
};
component.breadcrumb = [
rootNode,
{
id: '1',
name: 'node-1'
}
];
await component.updateComplete;

const notButton = await screen.findByText('node-1');
notButton.click();

expect(eventEmitted).toBeUndefined();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* -------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License.
* See License in the project root for license information.
* -------------------------------------------------------------------------------------------
*/

@import '../../styles/shared-sass-variables.scss';

$breadcrumb: ();

@include create-themes($breadcrumb);
Loading