Skip to content

Commit

Permalink
Fix this reference for JavaScript functions (#38725)
Browse files Browse the repository at this point in the history
  • Loading branch information
nwalters512 authored Jul 19, 2024
1 parent 74891cb commit 16d80a4
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 12 deletions.
2 changes: 1 addition & 1 deletion js/src/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ class Dropdown extends BaseComponent {

return {
...defaultBsPopperConfig,
...execute(this._config.popperConfig, [defaultBsPopperConfig])
...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
}
}

Expand Down
4 changes: 2 additions & 2 deletions js/src/tooltip.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ class Tooltip extends BaseComponent {
}

_resolvePossibleFunction(arg) {
return execute(arg, [this._element])
return execute(arg, [this._element, this._element])
}

_getPopperConfig(attachment) {
Expand Down Expand Up @@ -438,7 +438,7 @@ class Tooltip extends BaseComponent {

return {
...defaultBsPopperConfig,
...execute(this._config.popperConfig, [defaultBsPopperConfig])
...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
}
}

Expand Down
2 changes: 1 addition & 1 deletion js/src/util/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ const defineJQueryPlugin = plugin => {
}

const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
return typeof possibleCallback === 'function' ? possibleCallback(...args) : defaultValue
return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue
}

const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
Expand Down
2 changes: 1 addition & 1 deletion js/src/util/template-factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ class TemplateFactory extends Config {
}

_resolvePossibleFunction(arg) {
return execute(arg, [this])
return execute(arg, [undefined, this])
}

_putElementInTemplate(element, templateElement) {
Expand Down
5 changes: 4 additions & 1 deletion js/tests/unit/dropdown.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,10 @@ describe('Dropdown', () => {

const popperConfig = dropdown._getPopperConfig()

expect(getPopperConfig).toHaveBeenCalled()
// Ensure that the function was called with the default config.
expect(getPopperConfig).toHaveBeenCalledWith(jasmine.objectContaining({
placement: jasmine.any(String)
}))
expect(popperConfig.placement).toEqual('left')
})
})
Expand Down
54 changes: 54 additions & 0 deletions js/tests/unit/popover.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,60 @@ describe('Popover', () => {
})
})

it('should call content and title functions with trigger element', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#" data-foo="bar">BS twitter</a>'

const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl, {
title(el) {
return el.dataset.foo
},
content(el) {
return el.dataset.foo
}
})

popoverEl.addEventListener('shown.bs.popover', () => {
const popoverDisplayed = document.querySelector('.popover')

expect(popoverDisplayed).not.toBeNull()
expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('bar')
expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('bar')
resolve()
})

popover.show()
})
})

it('should call content and title functions with correct this value', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#" data-foo="bar">BS twitter</a>'

const popoverEl = fixtureEl.querySelector('a')
const popover = new Popover(popoverEl, {
title() {
return this.dataset.foo
},
content() {
return this.dataset.foo
}
})

popoverEl.addEventListener('shown.bs.popover', () => {
const popoverDisplayed = document.querySelector('.popover')

expect(popoverDisplayed).not.toBeNull()
expect(popoverDisplayed.querySelector('.popover-header').textContent).toEqual('bar')
expect(popoverDisplayed.querySelector('.popover-body').textContent).toEqual('bar')
resolve()
})

popover.show()
})
})

it('should show a popover with just content without having header', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#">Nice link</a>'
Expand Down
40 changes: 36 additions & 4 deletions js/tests/unit/tooltip.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,10 @@ describe('Tooltip', () => {

const popperConfig = tooltip._getPopperConfig('top')

expect(getPopperConfig).toHaveBeenCalled()
// Ensure that the function was called with the default config.
expect(getPopperConfig).toHaveBeenCalledWith(jasmine.objectContaining({
placement: jasmine.any(String)
}))
expect(popperConfig.placement).toEqual('left')
})

Expand Down Expand Up @@ -919,10 +922,12 @@ describe('Tooltip', () => {

it('should show a tooltip with custom class provided as a function in config', () => {
return new Promise(resolve => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip"></a>'
fixtureEl.innerHTML = '<a href="#" rel="tooltip" title="Another tooltip" data-class-a="custom-class-a" data-class-b="custom-class-b"></a>'

const spy = jasmine.createSpy('customClass').and.returnValue('custom-class')
const tooltipEl = fixtureEl.querySelector('a')
const spy = jasmine.createSpy('customClass').and.callFake(function (el) {
return `${el.dataset.classA} ${this.dataset.classB}`
})
const tooltip = new Tooltip(tooltipEl, {
customClass: spy
})
Expand All @@ -931,7 +936,8 @@ describe('Tooltip', () => {
const tip = document.querySelector('.tooltip')
expect(tip).not.toBeNull()
expect(spy).toHaveBeenCalled()
expect(tip).toHaveClass('custom-class')
expect(tip).toHaveClass('custom-class-a')
expect(tip).toHaveClass('custom-class-b')
resolve()
})

Expand Down Expand Up @@ -1337,6 +1343,32 @@ describe('Tooltip', () => {

expect(tooltip._getTitle()).toEqual('test')
})

it('should call title function with trigger element', () => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-foo="bar"></a>'

const tooltipEl = fixtureEl.querySelector('a')
const tooltip = new Tooltip(tooltipEl, {
title(el) {
return el.dataset.foo
}
})

expect(tooltip._getTitle()).toEqual('bar')
})

it('should call title function with correct this value', () => {
fixtureEl.innerHTML = '<a href="#" rel="tooltip" data-foo="bar"></a>'

const tooltipEl = fixtureEl.querySelector('a')
const tooltip = new Tooltip(tooltipEl, {
title() {
return this.dataset.foo
}
})

expect(tooltip._getTitle()).toEqual('bar')
})
})

describe('getInstance', () => {
Expand Down
4 changes: 2 additions & 2 deletions js/tests/unit/util/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -521,10 +521,10 @@ describe('Util', () => {

it('should execute if arg is function & return the result', () => {
const functionFoo = (num1, num2 = 10) => num1 + num2
const resultFoo = Util.execute(functionFoo, [4, 5])
const resultFoo = Util.execute(functionFoo, [undefined, 4, 5])
expect(resultFoo).toBe(9)

const resultFoo1 = Util.execute(functionFoo, [4])
const resultFoo1 = Util.execute(functionFoo, [undefined, 4])
expect(resultFoo1).toBe(14)

const functionBar = () => 'foo'
Expand Down

0 comments on commit 16d80a4

Please sign in to comment.