Skip to content

Commit

Permalink
feat(clipboard): add test
Browse files Browse the repository at this point in the history
  • Loading branch information
aesteves60 authored and dpellier committed Aug 3, 2023
1 parent 9acd899 commit 9113322
Show file tree
Hide file tree
Showing 20 changed files with 185 additions and 134 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { OdsComponentAttributes } from '../ods-component-attributes';

export interface OdsClipboardAttributes extends OdsComponentAttributes {
/**
* Clipboard attribute description
*/
/** Indicates if the input is full width or not: see component principles */
flex?: boolean;

/** Input text value */
value: string;

/** Disabled the input, the focus, and the tooltip */
disabled?: boolean;
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
import { OdsClipboard } from './ods-clipboard';
import { OdsComponentController } from '../ods-component-controller';
import { writeOnClipboard } from '../../utils/clipboard/write-on-clipboard';

/**
* common controller logic for cmpnt component used by the different implementations.
* it contains all the glue between framework implementation and the third party service.
*/
export class OdsClipboardController extends OdsComponentController<OdsClipboard> {
// private readonly logger = new OdsLogger('OdsClipboardController');

constructor(component: OdsClipboard) {
super(component);
}

/**
* Attributes validation documentation
*/
validateAttributes(): void {
return;
async handlerClick(value: string): Promise<void> {
await writeOnClipboard(value);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { OdsClipboardAttributes } from './ods-clipboard-attributes';

export const odsClipboardDefaultAttributesDoc = {
// default attributes
export const odsClipboardDefaultAttributesDoc = {
flex: false,
value: '',
disabled: false,
} as const;

export const odsClipboardDefaultAttributes = odsClipboardDefaultAttributesDoc as OdsClipboardAttributes;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OdsComponentEvents } from '../ods-component-events';

export interface OdsClipboardEvents extends OdsComponentEvents {
// Events
odsClipboardCopied: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export function writeOnClipboard(textToWrite: string): Promise<void> {
console.log('test', textToWrite);
return navigator.clipboard.writeText(textToWrite);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {Description} from '@storybook/addon-docs';

[//]: # (import Specs from '@ovhcloud/ods-core/src/components/clipboard/docs/spec.md';)
import Specs from '@ovhcloud/ods-core/src/components/clipboard/docs/spec.md';
import SpecsClipboardContents from './specifications-clipboard-contents.mdx';
import SpecsClipboardTests from './specifications-clipboard-tests.mdx';

[//]: # (<Description>{Specs}</Description>)
<Description>{Specs}</Description>

## Contents
<SpecsClipboardContents />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import {
OdsComponentAttributes2StringAttributes,
odsClipboardDefaultAttributes,
} from '@ovhcloud/ods-core';
import { OdsCreateAttributes, OdsStringAttributes2Str, odsClipboardBaseAttributes } from '@ovhcloud/ods-testing';
import { OdsCreateAttributes, OdsStringAttributes2Str } from '@ovhcloud/ods-testing';

describe('e2e:osds-clipboard', () => {
let page: E2EPage;
let el: E2EElement;

async function setup({ attributes = {}, html = `` }: { attributes?: Partial<OdsClipboardAttributes>, html?: string } = {}) {
const minimalAttributes: OdsClipboardAttributes = OdsCreateAttributes(attributes, odsClipboardBaseAttributes);
const minimalAttributes: OdsClipboardAttributes = OdsCreateAttributes(attributes, odsClipboardDefaultAttributes);
const stringAttributes = OdsComponentAttributes2StringAttributes<OdsClipboardAttributes>(minimalAttributes, odsClipboardDefaultAttributes);

page = await newE2EPage();
Expand All @@ -25,6 +25,29 @@ describe('e2e:osds-clipboard', () => {
}

describe('screenshots', () => {
// Screenshot testing
[false, true].forEach((flex) => {
[false, true].forEach((disabled) => {
[undefined, 'value'].forEach((value) => {
it([flex, disabled, value].join(', '), async () => {
await setup({
attributes: {
flex,
disabled,
value
},
});
await page.waitForChanges();

await page.evaluate(() => {
const element = document.querySelector('osds-clipboard') as HTMLElement;
return { width: element.clientWidth, height: element.clientHeight };
});
await page.setViewport({ width: 600, height: 600 });
const results = await page.compareScreenshot('clipboard', { fullPage: false, omitBackground: true });
expect(results).toMatchScreenshot({ allowableMismatchedRatio: 0 })
});
});
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,28 +1,56 @@
import { E2EElement, E2EPage, newE2EPage } from '@stencil/core/testing';
import { OdsClipboardAttributes, OdsComponentAttributes2StringAttributes, odsClipboardDefaultAttributes } from '@ovhcloud/ods-core';
import { OdsCreateAttributes, OdsStringAttributes2Str, odsClipboardBaseAttributes } from '@ovhcloud/ods-testing';
import { OdsCreateAttributes, OdsStringAttributes2Str } from '@ovhcloud/ods-testing';

describe('e2e:osds-clipboard', () => {
let page: E2EPage;
let el: E2EElement;
let input: E2EElement;

async function setup({ attributes }: { attributes: Partial<OdsClipboardAttributes> }) {
const minimalAttributes: OdsClipboardAttributes = OdsCreateAttributes(attributes, odsClipboardBaseAttributes);
const minimalAttributes: OdsClipboardAttributes = OdsCreateAttributes(attributes, odsClipboardDefaultAttributes);
const stringAttributes = OdsComponentAttributes2StringAttributes<OdsClipboardAttributes>(minimalAttributes, odsClipboardDefaultAttributes);

page = await newE2EPage();
const origin = await page.evaluate(() => window.origin);

const browserContext = page.browserContext();
await browserContext.overridePermissions(origin, ['clipboard-write', 'clipboard-read']);
await page.setContent(`<osds-clipboard ${OdsStringAttributes2Str(stringAttributes)}></osds-clipboard>`);
await page.evaluate(() => document.body.style.setProperty('margin', '0px'));

el = await page.find('osds-clipboard');
input = await page.find('osds-clipboard >>> osds-input');
await page.waitForChanges();
}

it('should render', async () => {
await setup({ attributes: {} });
expect(el).not.toBeNull();
expect(el).toHaveClass('hydrated');

// E2E testing
expect(input).not.toBeNull();
expect(input).toHaveClass('hydrated');
});

it.only('should copy the input value', async () => {
const value = 'text to copy';

await setup({ attributes: { value } });

await input.click();

expect(await page.evaluate(() => navigator.clipboard.readText())).toBe(value);
});

// it('should not copy the input value because of disabled', async () => {
// const value = 'text to copy';
// await setup({ attributes: { value, disabled: true } });
// await page.evaluate(() => navigator.clipboard.writeText(''));

// await input.click();

// expect(await page.evaluate(() => navigator.clipboard.readText())).toBe('');
// });

});
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
@import 'styles/osds-clipboard.mixins';
@import 'styles/osds-clipboard.color';
@import 'styles/osds-clipboard.size';
@import 'styles/osds-clipboard.typography';
@import '~@ovhcloud/ods-theming/color/ods-theming-color';
@import '~@ovhcloud/ods-theming/ods-theme';

// CSS targeted only for this component
// /!\ for theming purposes, it has to be done in theming files
// (i.e. packages/libraries/theming/...)
:host {

}

:host([attribute]) {

}

// apply the theme template for the component
@include ods-theme-component() {
@include osds-clipboard-theme-color();
@include osds-clipboard-theme-size();
@include osds-clipboard-theme-typography();
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@ import {
import {
OdsCreateAttributes,
OdsStringAttributes2Str,
odsClipboardBaseAttributes,
odsUnitTestAttribute
} from '@ovhcloud/ods-testing';
import { SpecPage, newSpecPage } from '@stencil/core/testing';

import { OdsThemeColorIntentList } from '@ovhcloud/ods-theming';
import { OsdsClipboard } from './osds-clipboard';
import { getAttributeContextOptions } from '@ovhcloud/ods-stencil/libraries/stencil-testing';

Expand All @@ -23,13 +20,14 @@ describe('spec:osds-clipboard', () => {
let root: HTMLElement | undefined;
let instance: OsdsClipboard;
let controller: OdsClipboardController;
let input: HTMLElement;

afterEach(() => {
jest.clearAllMocks();
});

async function setup({ attributes = {} }: { attributes?: Partial<OdsClipboardAttributes> } = {}) {
const minimalAttributes: OdsClipboardAttributes = OdsCreateAttributes(attributes, odsClipboardBaseAttributes);
const minimalAttributes: OdsClipboardAttributes = OdsCreateAttributes(attributes, odsClipboardDefaultAttributes);
const stringAttributes = OdsComponentAttributes2StringAttributes<OdsClipboardAttributes>(minimalAttributes, odsClipboardDefaultAttributes);

page = await newSpecPage({
Expand All @@ -40,6 +38,7 @@ describe('spec:osds-clipboard', () => {
root = page.root;
instance = page.rootInstance;
controller = (OdsClipboardController as unknown as jest.SpyInstance<OdsClipboardController, unknown[]>).mock.instances[0];
input = root.shadowRoot.querySelector('osds-input');
}

it('should render', async () => {
Expand All @@ -55,14 +54,55 @@ describe('spec:osds-clipboard', () => {
setup
};

// Attributes Unit testing
describe('flex', () => {
odsUnitTestAttribute<OdsClipboardAttributes, 'flex'>({
...getAttributeContextOptions<OdsClipboardAttributes, OsdsClipboard, 'flex'>({
name: 'flex',
list: [true, false],
defaultValue: odsClipboardDefaultAttributes.flex,
...config
})
});
});

describe('disabled', () => {
odsUnitTestAttribute<OdsClipboardAttributes, 'disabled'>({
...getAttributeContextOptions<OdsClipboardAttributes, OsdsClipboard, 'disabled'>({
name: 'disabled',
list: [true, false],
defaultValue: odsClipboardDefaultAttributes.disabled,
...config
})
});
});

describe('value', () => {
odsUnitTestAttribute<OdsClipboardAttributes, 'value'>({
...getAttributeContextOptions<OdsClipboardAttributes, OsdsClipboard, 'value'>({
name: 'value',
list: ['', 'new value'],
defaultValue: odsClipboardDefaultAttributes.value,
...config
})
});
});
});

describe('controller', () => {
it('should call controller.validateAttributes', async () => {
await setup();
expect(controller.validateAttributes).toHaveBeenCalledWith();
expect(controller.validateAttributes).toHaveBeenCalledTimes(1);
describe('methods', () => {
it('should call handlerClick controller', async () => {
await setup({});
instance.handlerClick();
input.click();

expect(controller.handlerClick).toHaveBeenCalledTimes(2);
});

it('should not call handlerClick controller because of disabled', async () => {
await setup({ attributes: { disabled: true } });
instance.handlerClick();
input.click();

expect(controller.handlerClick).not.toHaveBeenCalled();
})
});
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { Component, Element, Host, h } from '@stencil/core';
import { Component, Element, Host, h, Prop, Event, EventEmitter } from '@stencil/core';
import {
OdsClipboard,
OdsClipboardController,
odsClipboardDefaultAttributes,
OdsClipboardEvents,
OdsClipboardMethods,
OdsIconName,
OdsInputType,
// odsClipboardDefaultAttributes
} from '@ovhcloud/ods-core';
import { OdsStencilEvents, OdsStencilMethods } from '@ovhcloud/ods-stencil/libraries/stencil-core';
import { OdsThemeColorIntent } from '@ovhcloud/ods-theming';

/**
* @slot (unnamed) - Clipboard content
Expand All @@ -20,26 +24,39 @@ export class OsdsClipboard implements OdsClipboard<OdsStencilMethods<OdsClipboar
controller: OdsClipboardController = new OdsClipboardController(this);
@Element() el!: HTMLElement;

// Component properties as @Prop
// ex: @Prop({ reflect: true }) public color?: OdsThemeColorIntent = odsClipboardDefaultAttributes.color;
/** @see OdsClipboardAttributes.flex */
@Prop({ reflect: true }) public flex?: boolean = odsClipboardDefaultAttributes.flex;

/**
* @see OdsClipboardBehavior.beforeRender
*/
beforeRender(): void {
/** @see OdsClipboardAttributes.value */
@Prop({ reflect: true }) public value: string = odsClipboardDefaultAttributes.value;

/** @see OdsClipboardAttributes.disabled */
@Prop({ reflect: true }) public disabled?: boolean = odsClipboardDefaultAttributes.disabled;

}

componentWillRender(): void {
/** @see OdsClipboardEvents.odsClipboardCopied */
@Event() odsClipboardCopied!: EventEmitter<string>;

handlerClick(): void {
if (this.disabled) {
return;
}
this.controller.handlerClick(this.value);
}

render() {

return (
<Host>

{/* UI template */}
<osds-input read-only
color={ OdsThemeColorIntent.primary }
disabled={ this.disabled }
flex={ this.flex }
icon={ OdsIconName.COPY }
type={ OdsInputType.text }
value={ this.value }
onClick={ () => this.handlerClick() }>
</osds-input>

</Host>
);
Expand Down
Loading

0 comments on commit 9113322

Please sign in to comment.