Skip to content

Commit

Permalink
Merge pull request #216 from github/switch-to-promise-batching-on-att…
Browse files Browse the repository at this point in the history
…ributechangedcallback

Switch to promise batching on attributechangedcallback
  • Loading branch information
keithamus committed Nov 28, 2022
2 parents dcf479f + a1bd31e commit 223bc5d
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 109 deletions.
8 changes: 5 additions & 3 deletions src/relative-time-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const dateObserver = new (class {

export default class RelativeTimeElement extends HTMLElement implements Intl.DateTimeFormatOptions {
#customTitle = false
#updating = false
#updating: false | Promise<void> = false

get #lang() {
return this.closest('[lang]')?.getAttribute('lang') ?? 'default'
Expand Down Expand Up @@ -341,12 +341,14 @@ export default class RelativeTimeElement extends HTMLElement implements Intl.Dat
this.#customTitle = newValue !== null && this.getFormattedTitle() !== newValue
}
if (!this.#updating && !(attrName === 'title' && this.#customTitle)) {
this.update()
this.#updating = (async () => {
await Promise.resolve()
this.update()
})()
}
}

update() {
this.#updating = true
const oldText: string = this.#renderRoot.textContent || ''
const oldTitle: string = this.getAttribute('title') || ''
let newTitle: string = oldTitle
Expand Down
35 changes: 24 additions & 11 deletions test/local-time.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,107 +12,120 @@ suite('local-time', function () {
fixture.innerHTML = ''
})

test('null getFormattedDate when datetime missing', function () {
test('null getFormattedDate when datetime missing', async () => {
const time = document.createElement('local-time')
time.setAttribute('format', '%Y-%m-%dT%H:%M:%SZ')
await Promise.resolve()
assert.isUndefined(time.getFormattedDate())
})

test('getFormattedDate returns empty string when format missing', function () {
test('getFormattedDate returns empty string when format missing', async () => {
const time = document.createElement('local-time')
time.setAttribute('datetime', '1970-01-01T00:00:00.000Z')
await Promise.resolve()
assert.equal(time.getFormattedDate(), '')
})

test('getFormattedDate with only date attributes', function () {
test('getFormattedDate with only date attributes', async () => {
const time = document.createElement('local-time')
time.setAttribute('datetime', '1970-01-01T00:00:00.000Z')
time.setAttribute('day', 'numeric')
time.setAttribute('month', 'short')
time.setAttribute('year', 'numeric')

const value = time.getFormattedDate()
await Promise.resolve()
assert.include(['Dec 31, 1969', '31 Dec 1969', 'Jan 1, 1970', '1 Jan 1970'], value)
})

test('getFormattedDate without year attribute', function () {
test('getFormattedDate without year attribute', async () => {
const time = document.createElement('local-time')
time.setAttribute('datetime', '1970-01-01T00:00:00.000Z')
time.setAttribute('day', 'numeric')
time.setAttribute('month', 'short')

const value = time.getFormattedDate()
await Promise.resolve()
assert.include(['Dec 31', '31 Dec', 'Jan 1', '1 Jan'], value)
})

test('getFormattedDate with only time attributes', function () {
test('getFormattedDate with only time attributes', async () => {
const time = document.createElement('local-time')
time.setAttribute('lang', 'en-US')
time.setAttribute('datetime', '1970-01-01T00:00:00.000Z')
time.setAttribute('hour', 'numeric')
time.setAttribute('minute', '2-digit')

await Promise.resolve()
if ('Intl' in window) {
assert.match(time.getFormattedDate(), /^\d{1,2}:\d\d (AM|PM)$/)
} else {
assert.match(time.getFormattedDate(), /^\d{2}:\d{2}$/)
}
})

test('ignores contents if datetime attribute is missing', function () {
test('ignores contents if datetime attribute is missing', async () => {
const time = document.createElement('local-time')
time.setAttribute('year', 'numeric')
await Promise.resolve()
assert.equal(time.shadowRoot.textContent, '')
})

test('sets formatted contents to format attribute', function () {
test('sets formatted contents to format attribute', async () => {
const time = document.createElement('local-time')
time.setAttribute('datetime', '1970-01-01T00:00:00.000Z')
time.setAttribute('year', 'numeric')
await Promise.resolve()
assert.include(['1969', '1970'], time.shadowRoot.textContent)
})

test('updates format when attributes change', function () {
test('updates format when attributes change', async () => {
const time = document.createElement('local-time')
time.setAttribute('datetime', '1970-01-01T00:00:00.000Z')

time.setAttribute('year', 'numeric')
await Promise.resolve()
assert.include(['1969', '1970'], time.shadowRoot.textContent)

time.setAttribute('year', '2-digit')
await Promise.resolve()
assert.include(['69', '70'], time.shadowRoot.textContent)
})

test('sets formatted contents when parsed element is upgraded', function () {
test('sets formatted contents when parsed element is upgraded', async () => {
const root = document.createElement('div')
root.innerHTML = '<local-time datetime="1970-01-01T00:00:00.000Z" year="numeric"></local-time>'
if ('CustomElements' in window) {
window.CustomElements.upgradeSubtree(root)
}
await Promise.resolve()
assert.include(['1969', '1970'], root.children[0].shadowRoot.textContent)
})
;('Intl' in window ? test : test.skip)('displays time zone name', function () {
;('Intl' in window ? test : test.skip)('displays time zone name', async () => {
const root = document.createElement('div')
root.innerHTML =
'<local-time datetime="1970-01-01T00:00:00.000Z" minute="2-digit" time-zone-name="short"></local-time>'
if ('CustomElements' in window) {
window.CustomElements.upgradeSubtree(root)
}
await Promise.resolve()
assert.match(root.children[0].shadowRoot.textContent, /^\d{1,2} (\w+([+-]\d+)?)$/)
assert.equal(root.children[0].shadowRoot.textContent, '0 GMT+4')
})

test('updates time zone when the `time-zone-name` attribute changes', function () {
test('updates time zone when the `time-zone-name` attribute changes', async () => {
const el = document.createElement('local-time')
el.setAttribute('lang', 'en-US')
el.setAttribute('datetime', '1970-01-01T00:00:00.000-08:00')
el.setAttribute('time-zone-name', 'short')

fixture.appendChild(el)
await Promise.resolve()
assert.equal(el.shadowRoot.textContent, '1/1/1970, GMT+4')

el.setAttribute('time-zone-name', 'long')

await Promise.resolve()
assert.equal(el.shadowRoot.textContent, '1/1/1970, Gulf Standard Time')
})
})
Loading

0 comments on commit 223bc5d

Please sign in to comment.