add test for compose, and emoji
This commit is contained in:
parent
b26fdc7f55
commit
2614e451b2
Binary file not shown.
Binary file not shown.
|
@ -2,6 +2,7 @@ import { cacheFirstUpdateAfter } from '../_utils/sync'
|
||||||
import { database } from '../_database/database'
|
import { database } from '../_database/database'
|
||||||
import { getCustomEmoji } from '../_api/emoji'
|
import { getCustomEmoji } from '../_api/emoji'
|
||||||
import { store } from '../_store/store'
|
import { store } from '../_store/store'
|
||||||
|
import { substring } from 'stringz'
|
||||||
|
|
||||||
export async function updateCustomEmojiForInstance (instanceName) {
|
export async function updateCustomEmojiForInstance (instanceName) {
|
||||||
await cacheFirstUpdateAfter(
|
await cacheFirstUpdateAfter(
|
||||||
|
@ -17,5 +18,12 @@ export async function updateCustomEmojiForInstance (instanceName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function insertEmoji (emoji) {
|
export function insertEmoji (emoji) {
|
||||||
store.set({emojiToInsert: emoji})
|
let idx = store.get('composeSelectionStart') || 0
|
||||||
|
let oldText = store.get('rawComposeText')
|
||||||
|
let pre = substring(oldText, 0, idx)
|
||||||
|
let post = substring(oldText, idx)
|
||||||
|
let newText = `${pre}:${emoji.shortcode}: ${post}`
|
||||||
|
store.set({
|
||||||
|
rawComposeText: newText
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
placeholder="What's on your mind?"
|
placeholder="What's on your mind?"
|
||||||
ref:textarea
|
ref:textarea
|
||||||
bind:value=$rawComposeText
|
bind:value=$rawComposeText
|
||||||
|
on:blur="onBlur()"
|
||||||
></textarea>
|
></textarea>
|
||||||
<style>
|
<style>
|
||||||
.compose-box-input {
|
.compose-box-input {
|
||||||
|
@ -48,34 +49,21 @@
|
||||||
this.store.set({composeText: composeText})
|
this.store.set({composeText: composeText})
|
||||||
saveText()
|
saveText()
|
||||||
}, {init: false})
|
}, {init: false})
|
||||||
|
|
||||||
this.observe('emojiToInsert', emojiToInsert => {
|
|
||||||
if (!emojiToInsert) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
let idx = this.refs.textarea.selectionStart || 0
|
|
||||||
let oldText = this.store.get('rawComposeText')
|
|
||||||
let newText = oldText.substring(0, idx) +
|
|
||||||
':' + emojiToInsert.shortcode + ': ' +
|
|
||||||
oldText.substring(idx)
|
|
||||||
this.store.set({
|
|
||||||
rawComposeText: newText,
|
|
||||||
emojiToInsert: null
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}, {init: false})
|
|
||||||
},
|
},
|
||||||
ondestroy() {
|
ondestroy() {
|
||||||
mark('autosize.destroy()')
|
mark('autosize.destroy()')
|
||||||
autosize.destroy(this.refs.textarea)
|
autosize.destroy(this.refs.textarea)
|
||||||
stop('autosize.destroy()')
|
stop('autosize.destroy()')
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
onBlur() {
|
||||||
|
this.store.set({composeSelectionStart: this.refs.textarea.selectionStart})
|
||||||
|
}
|
||||||
|
},
|
||||||
store: () => store,
|
store: () => store,
|
||||||
computed: {
|
computed: {
|
||||||
rawComposeText: ($rawComposeText) => $rawComposeText,
|
rawComposeText: ($rawComposeText) => $rawComposeText,
|
||||||
currentComposeText: ($currentComposeText) => $currentComposeText,
|
currentComposeText: ($currentComposeText) => $currentComposeText
|
||||||
emojiToInsert: ($emojiToInsert) => $emojiToInsert
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -34,15 +34,13 @@
|
||||||
store: () => store,
|
store: () => store,
|
||||||
computed: {
|
computed: {
|
||||||
inputLengthToDisplay: ($rawComposeTextLength) => {
|
inputLengthToDisplay: ($rawComposeTextLength) => {
|
||||||
return ($rawComposeTextLength <= CHAR_LIMIT
|
return CHAR_LIMIT - $rawComposeTextLength
|
||||||
? $rawComposeTextLength
|
|
||||||
: CHAR_LIMIT - $rawComposeTextLength)
|
|
||||||
},
|
},
|
||||||
inputLengthLabel: ($rawComposeTextOverLimit, inputLengthToDisplay) => {
|
inputLengthLabel: ($rawComposeTextOverLimit, inputLengthToDisplay) => {
|
||||||
if ($rawComposeTextOverLimit) {
|
if ($rawComposeTextOverLimit) {
|
||||||
return `${inputLengthToDisplay} characters over limit`
|
return `${inputLengthToDisplay} characters over limit`
|
||||||
} else {
|
} else {
|
||||||
return `${inputLengthToDisplay} characters`
|
return `${inputLengthToDisplay} characters remaining`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
.custom-emoji-list {
|
.custom-emoji-list {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(48px, 1fr));
|
||||||
grid-gap: 5px;
|
grid-gap: 5px;
|
||||||
padding: 20px 10px;
|
padding: 20px 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
import {
|
|
||||||
composeButton, composeInput, composeLengthIndicator, getUrl, homeNavButton, notificationsNavButton
|
|
||||||
} from '../utils'
|
|
||||||
import { foobarRole } from '../roles'
|
|
||||||
import times from 'lodash/times'
|
|
||||||
|
|
||||||
fixture`12-compose-limits.js`
|
|
||||||
.page`http://localhost:4002`
|
|
||||||
|
|
||||||
test('shows compose limits', async t => {
|
|
||||||
await t.useRole(foobarRole)
|
|
||||||
.hover(composeInput)
|
|
||||||
.expect(composeLengthIndicator.innerText).eql('0')
|
|
||||||
.expect(composeButton.getAttribute('disabled')).eql('')
|
|
||||||
.typeText(composeInput, 'typing some text')
|
|
||||||
.expect(composeLengthIndicator.innerText).eql('16')
|
|
||||||
.expect(composeButton.hasAttribute('disabled')).notOk()
|
|
||||||
.typeText(composeInput, times(50, () => 'hello world').join(' '), {replace: true, paste: true})
|
|
||||||
.expect(composeLengthIndicator.innerText).eql('-99')
|
|
||||||
.expect(composeButton.getAttribute('disabled')).eql('')
|
|
||||||
.typeText(composeInput, 'hello world', {replace: true})
|
|
||||||
.click(notificationsNavButton)
|
|
||||||
.expect(getUrl()).contains('/notifications')
|
|
||||||
.click(homeNavButton)
|
|
||||||
.expect(getUrl()).eql('http://localhost:4002/')
|
|
||||||
.expect(composeInput.value).eql('hello world')
|
|
||||||
.expect(composeLengthIndicator.innerText).eql('11')
|
|
||||||
.expect(composeButton.hasAttribute('disabled')).notOk()
|
|
||||||
.selectText(composeInput)
|
|
||||||
.pressKey('delete')
|
|
||||||
.expect(composeInput.value).eql('')
|
|
||||||
.expect(composeLengthIndicator.innerText).eql('0')
|
|
||||||
.expect(composeButton.getAttribute('disabled')).eql('')
|
|
||||||
})
|
|
83
tests/spec/12-compose.js
Normal file
83
tests/spec/12-compose.js
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
import { Selector as $ } from 'testcafe'
|
||||||
|
import {
|
||||||
|
composeButton, composeInput, composeLengthIndicator, emojiButton, getComposeSelectionStart, getUrl,
|
||||||
|
homeNavButton,
|
||||||
|
notificationsNavButton
|
||||||
|
} from '../utils'
|
||||||
|
import { foobarRole } from '../roles'
|
||||||
|
import times from 'lodash/times'
|
||||||
|
|
||||||
|
fixture`12-compose.js`
|
||||||
|
.page`http://localhost:4002`
|
||||||
|
|
||||||
|
test('shows compose limits', async t => {
|
||||||
|
await t.useRole(foobarRole)
|
||||||
|
.hover(composeInput)
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('500')
|
||||||
|
.expect(composeButton.getAttribute('disabled')).eql('')
|
||||||
|
.typeText(composeInput, 'typing some text')
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('484')
|
||||||
|
.expect(composeButton.hasAttribute('disabled')).notOk()
|
||||||
|
.typeText(composeInput, times(50, () => 'hello world').join(' '), {replace: true, paste: true})
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('-99')
|
||||||
|
.expect(composeButton.getAttribute('disabled')).eql('')
|
||||||
|
.typeText(composeInput, 'hello world', {replace: true})
|
||||||
|
.click(notificationsNavButton)
|
||||||
|
.expect(getUrl()).contains('/notifications')
|
||||||
|
.click(homeNavButton)
|
||||||
|
.expect(getUrl()).eql('http://localhost:4002/')
|
||||||
|
.expect(composeInput.value).eql('hello world')
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('489')
|
||||||
|
.expect(composeButton.hasAttribute('disabled')).notOk()
|
||||||
|
.selectText(composeInput)
|
||||||
|
.pressKey('delete')
|
||||||
|
.expect(composeInput.value).eql('')
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('500')
|
||||||
|
.expect(composeButton.getAttribute('disabled')).eql('')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('shows compose limits for URLs/handles', async t => {
|
||||||
|
await t.useRole(foobarRole)
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('500')
|
||||||
|
.expect(composeButton.getAttribute('disabled')).eql('')
|
||||||
|
.typeText(composeInput, 'hello world ' +
|
||||||
|
'http://foo.bar.baz.whatever.example.com/hello ' +
|
||||||
|
'@reallylongnamethatstretchesonandon@foo.example.com', {paste: true})
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('429')
|
||||||
|
.expect(composeButton.hasAttribute('disabled')).notOk()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('shows compose limits for emoji', async t => {
|
||||||
|
await t.useRole(foobarRole)
|
||||||
|
.typeText(composeInput, 'hello world \ud83c\ude01 \ud83d\udc6a')
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('485')
|
||||||
|
.expect(composeButton.hasAttribute('disabled')).notOk()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('shows compose limits for custom emoji', async t => {
|
||||||
|
await t.useRole(foobarRole)
|
||||||
|
.typeText(composeInput, 'hello world ')
|
||||||
|
.click(emojiButton)
|
||||||
|
.click($('button img[title=":blobnom:"]'))
|
||||||
|
.expect(composeInput.value).eql('hello world :blobnom: ')
|
||||||
|
.expect(composeLengthIndicator.innerText).eql('478')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('inserts custom emoji correctly', async t => {
|
||||||
|
await t.useRole(foobarRole)
|
||||||
|
.typeText(composeInput, 'hello world')
|
||||||
|
.selectText(composeInput, 6, 6)
|
||||||
|
.expect(getComposeSelectionStart()).eql(6)
|
||||||
|
.click(emojiButton)
|
||||||
|
.click($('button img[title=":blobpats:"]'))
|
||||||
|
.expect(composeInput.value).eql('hello :blobpats: world')
|
||||||
|
.selectText(composeInput, 0, 0)
|
||||||
|
.expect(getComposeSelectionStart()).eql(0)
|
||||||
|
.click(emojiButton)
|
||||||
|
.click($('button img[title=":blobnom:"]'))
|
||||||
|
.expect(composeInput.value).eql(':blobnom: hello :blobpats: world')
|
||||||
|
.typeText(composeInput, ' foobar ')
|
||||||
|
.click(emojiButton)
|
||||||
|
.click($('button img[title=":blobpeek:"]'))
|
||||||
|
.expect(composeInput.value).eql(':blobnom: hello :blobpats: world foobar :blobpeek: ')
|
||||||
|
})
|
|
@ -13,6 +13,7 @@ export const formError = $('.form-error-user-error')
|
||||||
export const composeInput = $('.compose-box-input')
|
export const composeInput = $('.compose-box-input')
|
||||||
export const composeButton = $('.compose-box-button')
|
export const composeButton = $('.compose-box-button')
|
||||||
export const composeLengthIndicator = $('.compose-box-length')
|
export const composeLengthIndicator = $('.compose-box-length')
|
||||||
|
export const emojiButton = $('.compose-box-toolbar button:first-child')
|
||||||
|
|
||||||
export const favoritesCountElement = $('.status-favs-reblogs:nth-child(3)').addCustomDOMProperties({
|
export const favoritesCountElement = $('.status-favs-reblogs:nth-child(3)').addCustomDOMProperties({
|
||||||
innerCount: el => parseInt(el.innerText, 10)
|
innerCount: el => parseInt(el.innerText, 10)
|
||||||
|
@ -30,6 +31,10 @@ export const getActiveElementClass = exec(() =>
|
||||||
|
|
||||||
export const goBack = exec(() => window.history.back())
|
export const goBack = exec(() => window.history.back())
|
||||||
|
|
||||||
|
export const getComposeSelectionStart = exec(() => composeInput().selectionStart, {
|
||||||
|
dependencies: { composeInput }
|
||||||
|
})
|
||||||
|
|
||||||
export function getNthStatus (n) {
|
export function getNthStatus (n) {
|
||||||
return $(`div[aria-hidden="false"] > article[aria-posinset="${n}"]`)
|
return $(`div[aria-hidden="false"] > article[aria-posinset="${n}"]`)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue