Skip to content

Commit

Permalink
Added additional setter methods for select lists
Browse files Browse the repository at this point in the history
  • Loading branch information
nbeach committed Apr 14, 2020
1 parent c23c825 commit aadc414
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 3 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,26 @@ setTextAreaValue(element("textarea"), "Sasquatch") //Text area now has value "Sa
setCheckboxValue(element("input[type=check]"), true) //Checkbox is now checked
setRadioButton(element("input[type=radio]"), true) //Radio button is now selected
setSelectValue(element("select"), "Hancock") //Dropdown list now has the value "Hancock" selected
setSelectIndex(element("select"), 1) //Dropdown list now has the second option selected

```

These work with any DOM element reference, not just those returned by ng-units selection methods. They can be used
in traditional TestBed tests if desired.

#### Select lists and `[ngValue]`
Using `[ngValue]` for select list option bindings complicates setting a value slightly. The bound values can be things
other than strings, and consequently the value is not bound to the DOM. This makes determining which option to select more complicated.

If you know the index of the option you want you can use `setSelectIndex(element("select"), index)` to select the value

If you have access to a list of all the objects that are bound as option values you can use `setSelectFromOptions()` to select the value:
```typescript
const listOptions = [{ message: "Hello"}, { message: "Goodbye"}]
setSelectFromOptions(element("select"), { message: "Goodbye"}, listOptions)
```


#### Setting component inputs
Initial values for component inputs can be set prior to component instantiation (so they are properly present at
OnInit time) with the test builder method`.setInput()`.
Expand Down
115 changes: 115 additions & 0 deletions src/dom.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
selectComponents,
setCheckboxValue,
setRadioButton,
setSelectFromOptions,
setSelectIndex,
setSelectValue,
setTextAreaValue,
setTextInputValue,
Expand Down Expand Up @@ -119,6 +121,117 @@ describe("DOM", () => {
expect(subject.selectValue).to.equal("Adios")
})


})

describe("setSelectIndex() sets the value of select elements", () => {

it("when options have value attributes", () => {
@Component({
selector: "parent",
template: `
<select [(ngModel)]="selectValue">
<option></option>
<option value="Hola">Hello</option>
<option value="Adios">Goodbye</option>
</select>
`,
})
class TestComponent {
public selectValue = ""
}
const {subject, subjectElement, fixture} = setupTestModule(TestComponent)


setSelectIndex(subjectElement.querySelector("select"), 2)
fixture.detectChanges()

expect(subject.selectValue).to.equal("Adios")
})

it("when options have ngValue attributes", () => {
@Component({
selector: "parent",
template: `
<select [(ngModel)]="selectValue">
<option [ngValue]="null"></option>
<option [ngValue]="{ message: 'Hola' }">Hello</option>
<option [ngValue]="{ message: 'Adios' }">Goodbye</option>
</select>
`,
})
class TestComponent {
public selectValue = null
}
const {subject, subjectElement, fixture} = setupTestModule(TestComponent)

setSelectIndex(subjectElement.querySelector("select"), 1)
fixture.detectChanges()
expect(subject.selectValue).to.deep.equal({ message: "Hola" })

setSelectIndex(subjectElement.querySelector("select"), 0)
fixture.detectChanges()
expect(subject.selectValue).to.equal(null)
})

})

describe("setSelectFromOptions() sets the value of select elements", () => {

it("when options have ngValue attributes", () => {
@Component({
selector: "parent",
template: `
<select [(ngModel)]="selectValue">
<option *ngFor="let option of allOptions" [ngValue]="option">{{option?.label}}</option>
</select>
`,
})
class TestComponent {
public allOptions = [
null,
{ label: "Hello", value: "Hola" },
{ bar: "Adios" },
]

public selectValue = null
}
const {subject, subjectElement, fixture} = setupTestModule(TestComponent)


setSelectFromOptions(subjectElement.querySelector("select"), { bar: "Adios" }, subject.allOptions)
fixture.detectChanges()

expect(subject.selectValue).to.deep.equal({ bar: "Adios" })
})

it("when options have value attributes", () => {
@Component({
selector: "parent",
template: `
<select [(ngModel)]="selectValue">
<option *ngFor="let option of allOptions" value="{{option?.value}}">{{option?.label}}</option>
</select>
`,
})
class TestComponent {
public allOptions = [
null,
{ label: "Hello", value: "Hola" },
{ label: "Goodbye", value: "Adios" },
]

public selectValue = null
}
const {subject, subjectElement, fixture} = setupTestModule(TestComponent)


setSelectFromOptions(subjectElement.querySelector("select"), { label: "Goodbye", value: "Adios" }, subject.allOptions)
fixture.detectChanges()

expect(subject.selectValue).to.equal("Adios")
})

})

it('setRadioButton() sets the value of <input type="radio"> elements', () => {
Expand Down Expand Up @@ -464,6 +577,8 @@ describe("DOM", () => {
["name", "method" ],
[setTextInputValue.name, setTextInputValue ],
[setSelectValue.name, setSelectValue ],
[setSelectIndex.name, setSelectIndex ],
[setSelectFromOptions.name, setSelectFromOptions],
[setTextAreaValue.name, setTextAreaValue ],
[setCheckboxValue.name, setCheckboxValue ],
[setRadioButton.name, setRadioButton ],
Expand Down
18 changes: 15 additions & 3 deletions src/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {isNil, isString, findIndex} from "lodash"
import {By} from "@angular/platform-browser"
import {selectorOf} from "./selector-of"
import {Type} from "@angular/core"
import { isEqual } from "lodash"

function doIfElementPresent<T>(element: T | null, action: (item: T) => void) {
if (isNil(element)) {
Expand All @@ -20,13 +21,24 @@ export function setTextInputValue(input: Element | null, value: string): void {
})
}

export function setSelectIndex(selectBox: Element | null, index: number): void {
doIfElementPresent(selectBox, selectBox => {
(selectBox as any).selectedIndex = index
trigger(selectBox, "change")
})
}

export function setSelectValue(selectBox: Element | null, value: string): void {
doIfElementPresent(selectBox, selectBox => {
(selectBox as any).selectedIndex = findIndex(selectBox.children, option =>
option.getAttribute("value") === value || option.textContent === value)
const index = findIndex(selectBox.children, option => option.getAttribute("value") === value || option.textContent === value)
setSelectIndex(selectBox, index)
})
}

trigger(selectBox, "change")
export function setSelectFromOptions(selectBox: Element | null, optionToSelection: any, allOptions: any[]): void {
doIfElementPresent(selectBox, selectBox => {
const index = findIndex(allOptions, option => isEqual(option, optionToSelection))
setSelectIndex(selectBox, index)
})
}

Expand Down

0 comments on commit aadc414

Please sign in to comment.