From 7bda3ed227387ce89036c4133971a58bd3ec7157 Mon Sep 17 00:00:00 2001 From: varun shivaprasad Date: Thu, 24 May 2018 11:46:34 +0530 Subject: [PATCH 1/2] feat(oui switch): add oui-switch component --- packages/oui-angular/src/index.js | 4 +- packages/oui-angular/src/index.spec.js | 1 + packages/oui-field/README.md | 12 ++ packages/oui-switch/README.md | 68 +++++++ packages/oui-switch/src/index.js | 4 + packages/oui-switch/src/index.spec.js | 195 +++++++++++++++++++ packages/oui-switch/src/switch.component.js | 15 ++ packages/oui-switch/src/switch.controller.js | 27 +++ packages/oui-switch/src/switch.html | 8 + 9 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 packages/oui-switch/README.md create mode 100644 packages/oui-switch/src/index.js create mode 100644 packages/oui-switch/src/index.spec.js create mode 100644 packages/oui-switch/src/switch.component.js create mode 100644 packages/oui-switch/src/switch.controller.js create mode 100644 packages/oui-switch/src/switch.html diff --git a/packages/oui-angular/src/index.js b/packages/oui-angular/src/index.js index 471a1e6e..4b7bd45c 100644 --- a/packages/oui-angular/src/index.js +++ b/packages/oui-angular/src/index.js @@ -35,6 +35,7 @@ import "@oui-angular/oui-tile/src"; import "@oui-angular/oui-guide-menu/src"; import "@oui-angular/oui-header-tabs/src"; import "@oui-angular/oui-progress/src"; +import "@oui-angular/oui-switch/src"; angular.module("oui", [ "oui.button", @@ -73,5 +74,6 @@ angular.module("oui", [ "oui.tile", "oui.guide-menu", "oui.header-tabs", - "oui.progress" + "oui.progress", + "oui.switch" ]); diff --git a/packages/oui-angular/src/index.spec.js b/packages/oui-angular/src/index.spec.js index 3014b647..e24586f1 100644 --- a/packages/oui-angular/src/index.spec.js +++ b/packages/oui-angular/src/index.spec.js @@ -36,6 +36,7 @@ loadTests(require.context("../../oui-tile/src/", true, /.*((\.spec)|(index))$/)) loadTests(require.context("../../oui-guide-menu/src/", true, /.*((\.spec)|(index))$/)); loadTests(require.context("../../oui-header-tabs/src/", true, /.*((\.spec)|(index))$/)); loadTests(require.context("../../oui-progress/src/", true, /.*((\.spec)|(index))$/)); +loadTests(require.context("../../oui-switch/src/", true, /.*((\.spec)|(index))$/)); function loadTests (context) { context.keys().forEach(context); diff --git a/packages/oui-field/README.md b/packages/oui-field/README.md index be2e0e15..d20fcc7f 100644 --- a/packages/oui-field/README.md +++ b/packages/oui-field/README.md @@ -83,6 +83,18 @@ ``` +### Switch + +```html:preview +
+ + + +
+``` ### Radio diff --git a/packages/oui-switch/README.md b/packages/oui-switch/README.md new file mode 100644 index 00000000..f802143f --- /dev/null +++ b/packages/oui-switch/README.md @@ -0,0 +1,68 @@ +# Switch + + + +## Usage + +### Basic + +```html:preview + + + + +``` + +### Disabled + +```html:preview + + + + +``` + +### On change + +**Note:** Model will not be refreshed until the `on-change` callback as not finished. If you want to access the new model inside the `on-change` callback you need to use the `modelValue` variable as below. + +```html:preview +
+ + +
+Last onChange value: {{ $ctrl.lastOnChangeValue || ($ctrl.lastOnChangeValue === false && "false") || "undefined" }} +``` + +### Validation in form + +```html:preview +
+
+ + +
+ Is this form valid? : {{ form.$valid ? "yes" : "no" }} +
+``` + +## API + +| Attribute | Type | Binding | One-time Binding | Values | Default | Description +| ---- | ---- | ---- | ---- | ---- | ---- | ---- +| disabled | boolean | { + let TestUtils; + let $timeout; + + beforeEach(angular.mock.module("oui.switch")); + beforeEach(angular.mock.module("oui.test-utils")); + + beforeEach(inject((_TestUtils_, _$timeout_) => { + TestUtils = _TestUtils_; + $timeout = _$timeout_; + })); + + const getSwitchInputElement = (element) => element[0].querySelector("input[type=checkbox]"); + + describe("Component", () => { + + describe("input checkbox", () => { + it("should display a input (checkbox) element", () => { + const element = TestUtils.compileTemplate(""); + $timeout.flush(); + expect(getSwitchInputElement(element)).toBeTruthy(); + }); + }); + + describe("id attribute", () => { + it("should generate an id for the input when undefined", () => { + const element = TestUtils.compileTemplate(""); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("id")).toMatch(/^ouiSwitch\d+$/); + }); + + it("should set the id for the input when defined", () => { + const element = TestUtils.compileTemplate(""); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("id")).toBe("test"); + }); + }); + + describe("name attribute", () => { + it("should set the name attribute on input when defined", () => { + const element = TestUtils.compileTemplate(""); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("name")).toBe("test"); + }); + }); + + describe("model attribute", () => { + it("should display an unchecked switch when no model", () => { + const element = TestUtils.compileTemplate(""); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("checked")).toBe(false); + }); + + it("should display a on switch when true", () => { + const element = TestUtils.compileTemplate("", { + checked: true + }); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("checked")).toBe(true); + }); + + it("should display a an off switch when false", () => { + const element = TestUtils.compileTemplate("", { + checked: false + }); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("checked")).toBe(false); + }); + + it("should be updated when clicked", () => { + const element = TestUtils.compileTemplate("", { + currentModel: false + }); + + $timeout.flush(); + const $ctrl = TestUtils.getElementController(element); + const checkboxElement = getSwitchInputElement(element); + const $checkboxElement = angular.element(checkboxElement); + $checkboxElement.prop("checked", true); + $checkboxElement.triggerHandler("click"); + expect($ctrl.currentModel).toBe(true); + }); + }); + + describe("disabled attribute", () => { + it("should display an active switch when no attribute", () => { + const element = TestUtils.compileTemplate(""); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("disabled")).toBe(false); + }); + + it("should display a disabled switch when defined but no value", () => { + const element = TestUtils.compileTemplate(""); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("disabled")).toBe(true); + }); + + it("should display a disabled switch when true", () => { + const element = TestUtils.compileTemplate("", { + disabled: true + }); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("disabled")).toBe(true); + }); + }); + + describe("on-change attribute", () => { + it("should trigger callback when the switch is clicked", () => { + const onChangeSpy = jasmine.createSpy("onChangeSpy"); + + const element = TestUtils.compileTemplate("", { + onChange: onChangeSpy + }); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + const $checkboxElement = angular.element(checkboxElement); + $checkboxElement.prop("checked", true); + $checkboxElement.triggerHandler("click"); + expect(onChangeSpy).toHaveBeenCalledWith(true); + }); + }); + + describe("Validation", () => { + it("should apply a required validation with the required attribute without value", () => { + const element = TestUtils.compileTemplate(""); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("required")).toBe(true); + }); + + it("should apply a required validation with the required attribute when true", () => { + const element = TestUtils.compileTemplate(` + + `, { + isRequired: true + }); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("required")).toBe(true); + }); + + it("should not apply a required validation with the required attribute when false", () => { + const element = TestUtils.compileTemplate(` + + `, { + isRequired: false + }); + + $timeout.flush(); + const checkboxElement = getSwitchInputElement(element); + expect(angular.element(checkboxElement).prop("required")).toBe(false); + }); + + it("should be done if required attribute is defined", () => { + const element = TestUtils.compileTemplate(`
+ +
+ `, { + isRequired: true + }); + + $timeout.flush(); + const form = element.scope().form; + const checkboxElement = getSwitchInputElement(element); + const $checkboxElement = angular.element(checkboxElement); + expect(form.$valid).toBeFalsy(); + + $checkboxElement.prop("checked", true); + $checkboxElement.triggerHandler("click"); + expect(form.$valid).toBeTruthy(); + }); + }); + }); +}); diff --git a/packages/oui-switch/src/switch.component.js b/packages/oui-switch/src/switch.component.js new file mode 100644 index 00000000..39e639e3 --- /dev/null +++ b/packages/oui-switch/src/switch.component.js @@ -0,0 +1,15 @@ +import controller from "./switch.controller"; +import template from "./switch.html"; + +export default { + controller, + template, + bindings: { + disabled: " + this.$element + .addClass("oui-switch") + .removeAttr("id") + .removeAttr("name") + ); + } +} diff --git a/packages/oui-switch/src/switch.html b/packages/oui-switch/src/switch.html new file mode 100644 index 00000000..56e2d2ec --- /dev/null +++ b/packages/oui-switch/src/switch.html @@ -0,0 +1,8 @@ + From 77e0d0642dab958bf276031b0944fc1bf69be331 Mon Sep 17 00:00:00 2001 From: Axel Peter Date: Fri, 29 Jun 2018 15:55:33 +0200 Subject: [PATCH 2/2] docs(oui-switch): fix validation example --- packages/oui-switch/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/oui-switch/README.md b/packages/oui-switch/README.md index f802143f..e1170745 100644 --- a/packages/oui-switch/README.md +++ b/packages/oui-switch/README.md @@ -47,12 +47,12 @@ model="false"> ```html:preview
-
- Is this form valid? : {{ form.$valid ? "yes" : "no" }} + Is this form valid? : {{ switchForm.$valid ? "yes" : "no" }}
```