Skip to content

Commit

Permalink
Merge branch 'master' into fix/SNOW-364
Browse files Browse the repository at this point in the history
  • Loading branch information
mikegron committed Jul 7, 2020
2 parents 763b85b + 9a11f1d commit d98ab9a
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 46 deletions.
30 changes: 21 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@
[![Coverage Status](https://coveralls.io/repos/github/coveo/search-ui-extensions/badge.svg?branch=master)](https://coveralls.io/github/coveo/search-ui-extensions?branch=master)
[![Known Vulnerabilities](https://snyk.io/test/github/coveo/search-ui-extensions/badge.svg?targetFile=package.json)](https://snyk.io/test/github/coveo/search-ui-extensions?targetFile=package.json)

This repository contains additionnal components meant to be used in conjunction with [Coveo Javascript Search Framework](https://github.com/coveo/search-ui) to provide additionnal functionnalities.
This repository contains new components meant to be used in conjunction with the [Coveo Javascript Search Framework](https://github.com/coveo/search-ui) to provide additional functionalities.

## Setup

Requires Node JS >= 8.0.

1. `npm install`

2. `npm run build`

## Structure

The code is written in [typescript](http://www.typescriptlang.org/) and compiled using [webpack](https://webpack.github.io/).
The code is written in [TypeScript](http://www.typescriptlang.org/) and compiled using [webpack](https://webpack.github.io/).

- Under the `pages` folder, you have a working search page (index.html). At build time, it is copied to the `bin` folder.

- It references 2 style sheets (the base one from the Coveo Javascript Search Framework, and the one from the extension).
- It references 3 javascript file (the extension one built in this project, and the basic templates and library scripts).
- It references 2 style sheets (the base one from the Coveo JavaScript Search Framework, and the one from the extension).

- It references 3 JavaScript files (i.e., the extension one built in this project, the basic templates, and the library scripts).

- Under the `src` folder, you have all the typescript source code for the custom components, with `src/Index.ts` being the starting point of the application.

Expand All @@ -31,24 +33,34 @@ The code is written in [typescript](http://www.typescriptlang.org/) and compiled

## Build tasks

- `npm run setup` will copy the needed ressources (`index.html`, `templates`, etc.) in the `bin` folder.
- `npm run setup` will copy the needed resources (`index.html`, `templates`, etc.) in the `bin` folder.

- `npm run css` will build the sass files into a css file in the `bin` folder.
- `npm run build` will run the `setup`, `css` task, then compile the typescript code.

- `npm run build` will run the `setup` and `css` tasks. It will then compile the TypeScript code.

## Dev

`npm run dev` will start a [webpack dev server](https://webpack.github.io/docs/webpack-dev-server.html). After it finishes, load [http://localhost:8080/pages/attached_result.html](http://localhost:8080/pages/attached_result.html) in a browser, and the `index.html` page should load.

Then, anytime you hit save in a typescript file, the server will reload your application.
Then, anytime you save a TypeScript file, the server will reload your application.

## Tests

- `npm run test` will execute the tests one time and give you the report
- `npm run watchTest` will watch changes and reexecute the tests and coverage when saving a file.
- `npm run test` will execute the tests one time and generate the report.

- `npm run watchTest` will watch changes and re-execute the tests and coverage when saving a file.

## Running functional tests

1. `npm run dev` will start the developer server.

2. `npx cypress run` will run the cypress functional tests suite.

To add a new test suite simply add a new spec file in the `./cypress/integration/` folder.

## Compatibility

The components provided in this repository should be used as examples to build your own components. Since this project is still in the pre-release phase, backward compatibility of the compiled JavaScript is not guaranteed. Note that the TypeScript definitions could also be modified without notice.

As new releases could impact your implementation, we strongly recommend that you validate the content of each new release before upgrading to a newer version.
16 changes: 14 additions & 2 deletions pages/toggle_action_button.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,23 @@
<div>
<h2>Toggle Button</h2>
<br />
<button
class="CoveoToggleActionButton"
data-activate-icon='&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 78.997 78.997" height="298.571" width="298.571"&gt;&lt;circle r="39.499" cy="120.385" cx="84.1" transform="translate(-44.601 -80.887)"/&gt;&lt;/svg&gt;'
data-activate-tooltip="Activate feature"
data-deactivate-tooltip="Deactivate feature"
data-deactivate-icon='&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 78.997 78.997" height="298.571" width="298.571"&gt;&lt;path d="M39.434 0A39.499 39.499 0 000 39.498a39.499 39.499 0 0039.498 39.5 39.499 39.499 0 0039.5-39.5A39.499 39.499 0 0039.497 0a39.499 39.499 0 00-.064 0zm.59 7.273a31.948 31.948 0 0131.948 31.949A31.948 31.948 0 0140.023 71.17 31.948 31.948 0 018.075 39.222 31.948 31.948 0 0140.023 7.273z"/&gt;&lt;/svg&gt;'
></button>
</div>

<div>
<h2>Toggle Button (legacy options)</h2>
<br />
<button
class="CoveoToggleActionButton"
data-deactivated-icon='&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 78.997 78.997" height="298.571" width="298.571"&gt;&lt;circle r="39.499" cy="120.385" cx="84.1" transform="translate(-44.601 -80.887)"/&gt;&lt;/svg&gt;'
data-deactivated-tooltip="Normal tooltip"
data-activated-tooltip="Activated tooltip"
data-deactivated-tooltip="Activate feature"
data-activated-tooltip="Deactivate feature"
data-activated-icon='&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 78.997 78.997" height="298.571" width="298.571"&gt;&lt;path d="M39.434 0A39.499 39.499 0 000 39.498a39.499 39.499 0 0039.498 39.5 39.499 39.499 0 0039.5-39.5A39.499 39.499 0 0039.497 0a39.499 39.499 0 00-.064 0zm.59 7.273a31.948 31.948 0 0131.948 31.949A31.948 31.948 0 0140.023 71.17 31.948 31.948 0 018.075 39.222 31.948 31.948 0 0140.023 7.273z"/&gt;&lt;/svg&gt;'
></button>
</div>
Expand Down
46 changes: 23 additions & 23 deletions src/components/ActionButton/ToggleActionButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { ComponentOptions, IResultsComponentBindings, Component, Initialization
import { ActionButton } from './ActionButton';

export interface IToggleActionButtonOptions {
activatedIcon: string;
activatedTooltip: string;
deactivatedIcon: string;
deactivatedTooltip: string;
activateIcon: string;
activateTooltip: string;
deactivateIcon: string;
deactivateTooltip: string;
click?: () => void;
activate?: () => void;
deactivate?: () => void;
Expand All @@ -17,7 +17,8 @@ export class ToggleActionButton extends Component {

static options: IToggleActionButtonOptions = {
/**
* Specifies the button icon when the button is activated.
* Specifies the button SVG icon displayed to activate the button.
* Note: The SVG markup has to be HTML encoded when set using the HTML attributes.
*
* Default is the empty string.
*
Expand All @@ -30,25 +31,24 @@ export class ToggleActionButton extends Component {
* The attribute would be set like this:
*
* ```html
* <button class='CoveoToggleActionButton' data-activated-icon='&lt;svg width=&quot;1em&quot; height=&quot;1em&quot;&gt;...&lt;/svg&gt;'></button>
* <button class='CoveoToggleActionButton' data-activate-icon='&lt;svg width=&quot;1em&quot; height=&quot;1em&quot;&gt;...&lt;/svg&gt;'></button>
* ```
*/
activatedIcon: ComponentOptions.buildStringOption(),
activateIcon: ComponentOptions.buildStringOption({ alias: 'deactivatedIcon' }),

/**
* Specifies the button tooltip when the button is activated.
* Specifies the button tooltip text displayed to activate the button.
*
* Default is the empty string.
*
* ```html
* <button class='CoveoToggleActionButton' data-activated-tooltip='My activated button tooltip'></button>
* <button class='CoveoToggleActionButton' data-activate-tooltip='Activate the feature'></button>
* ```
*/
activatedTooltip: ComponentOptions.buildStringOption(),
activateTooltip: ComponentOptions.buildStringOption({ alias: 'deactivatedTooltip' }),

/**
* Specifies the button SVG icon when the button is deactivated.
* Note: The SVG markup has to be HTML encoded when set using the HTML attributes.
* Specifies the button icon displayed to deactivate the button.
*
* Default is the empty string.
*
Expand All @@ -61,21 +61,21 @@ export class ToggleActionButton extends Component {
* The attribute would be set like this:
*
* ```html
* <button class='CoveoToggleActionButton' data-deactivated-icon='&lt;svg width=&quot;1em&quot; height=&quot;1em&quot;&gt;...&lt;/svg&gt;'></button>
* <button class='CoveoToggleActionButton' data-deactivate-icon='&lt;svg width=&quot;1em&quot; height=&quot;1em&quot;&gt;...&lt;/svg&gt;'></button>
* ```
*/
deactivatedIcon: ComponentOptions.buildStringOption(),
deactivateIcon: ComponentOptions.buildStringOption({ alias: 'activatedIcon' }),

/**
* Specifies the button tooltip text when the button is deactivated.
* Specifies the button tooltip displayed to deactivate the button.
*
* Default is the empty string.
*
* ```html
* <button class='CoveoToggleActionButton' data-deactivated-tooltip='My button tooltip'></button>
* <button class='CoveoToggleActionButton' data-deactivate-tooltip='Deactivate the feature'></button>
* ```
*/
deactivatedTooltip: ComponentOptions.buildStringOption(),
deactivateTooltip: ComponentOptions.buildStringOption({ alias: 'activatedTooltip' }),

/**
* Specifies the handler called when the button is clicked.
Expand Down Expand Up @@ -152,8 +152,8 @@ export class ToggleActionButton extends Component {
this.innerActionButton = new ActionButton(
this.element,
{
icon: this.options.deactivatedIcon,
tooltip: this.options.deactivatedTooltip,
icon: this.options.activateIcon,
tooltip: this.options.activateTooltip,
click: () => this.onClick()
},
bindings
Expand All @@ -167,14 +167,14 @@ export class ToggleActionButton extends Component {
this.element.classList.add(ToggleActionButton.ACTIVATED_CLASS_NAME);
this.element.setAttribute('aria-pressed', 'true');

this.innerActionButton.updateIcon(this.options.activatedIcon);
this.innerActionButton.updateTooltip(this.options.activatedTooltip);
this.innerActionButton.updateIcon(this.options.deactivateIcon);
this.innerActionButton.updateTooltip(this.options.deactivateTooltip);
} else {
this.element.classList.remove(ToggleActionButton.ACTIVATED_CLASS_NAME);
this.element.setAttribute('aria-pressed', 'false');

this.innerActionButton.updateIcon(this.options.deactivatedIcon);
this.innerActionButton.updateTooltip(this.options.deactivatedTooltip);
this.innerActionButton.updateIcon(this.options.activateIcon);
this.innerActionButton.updateTooltip(this.options.activateTooltip);
}
}
}
Expand Down
45 changes: 33 additions & 12 deletions tests/components/ActionButton/ToggleActionButton.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Mock } from 'coveo-search-ui-tests';
import { IToggleActionButtonOptions, ToggleActionButton } from '../../../src/components/ActionButton/ToggleActionButton';
import * as icons from '../../../src/utils/icons';
import { ActionButton } from '../../../src/components/ActionButton/ActionButton';
import { IComponentOptions } from 'coveo-search-ui';

describe('ToggleActionButton', () => {
let sandbox: SinonSandbox;
Expand All @@ -27,10 +28,10 @@ describe('ToggleActionButton', () => {

beforeEach(() => {
options = {
activatedIcon: icons.duplicate,
activatedTooltip: 'activated tooltip',
deactivatedIcon: icons.copy,
deactivatedTooltip: 'tooltip',
activateIcon: icons.copy,
activateTooltip: 'Activate feature',
deactivateIcon: icons.duplicate,
deactivateTooltip: 'Deactivate feature',
click: clickSpy,
activate: activateSpy,
deactivate: deactivateSpy
Expand All @@ -52,6 +53,11 @@ describe('ToggleActionButton', () => {
return componentSetup.cmp;
}

function getOption(optionName: string): IComponentOptions<any> {
const dictOptions = ToggleActionButton.options as { [key: string]: any };
return dictOptions[optionName] as IComponentOptions<any>;
}

describe('clicking the button', () => {
beforeEach(() => {
Coveo.$$(testSubject.element).trigger('click');
Expand Down Expand Up @@ -86,12 +92,12 @@ describe('ToggleActionButton', () => {
expect(attributeValue).toEqual('true');
});

it('should update button with activated icon', () => {
expect(updateIconSpy.calledWith(options.activatedIcon)).toBeTrue();
it('should update button with deactivate icon', () => {
expect(updateIconSpy.calledWith(options.deactivateIcon)).toBeTrue();
});

it('should update button with activated tooltip', () => {
expect(updateTooltipSpy.calledWith(options.activatedTooltip)).toBeTrue();
it('should update button with deactivate tooltip', () => {
expect(updateTooltipSpy.calledWith(options.deactivateTooltip)).toBeTrue();
});
});

Expand Down Expand Up @@ -121,12 +127,27 @@ describe('ToggleActionButton', () => {
expect(attributeValue).toEqual('false');
});

it('should update button with deactivated icon', () => {
expect(updateIconSpy.calledWith(options.deactivatedIcon)).toBeTrue();
it('should update button with activate icon', () => {
expect(updateIconSpy.calledWith(options.activateIcon)).toBeTrue();
});

it('should update button with deactivated tooltip', () => {
expect(updateTooltipSpy.calledWith(options.deactivatedTooltip)).toBeTrue();
it('should update button with activate tooltip', () => {
expect(updateTooltipSpy.calledWith(options.activateTooltip)).toBeTrue();
});
});

describe('legacy options compatibility', () => {
[
{ legacy: 'activatedIcon', current: 'deactivateIcon' },
{ legacy: 'activatedTooltip', current: 'deactivateTooltip' },
{ legacy: 'deactivatedIcon', current: 'activateIcon' },
{ legacy: 'deactivatedTooltip', current: 'activateTooltip' }
].forEach(({ legacy, current }) => {
it(`should support legacy '${legacy}' option through '${current}'`, () => {
const option = getOption(current);

expect(option.alias).toContain(legacy);
});
});
});
});

0 comments on commit d98ab9a

Please sign in to comment.