biome format --write
This commit is contained in:
parent
8372348148
commit
9262e803ec
415 changed files with 54076 additions and 17419 deletions
|
|
@ -17,10 +17,14 @@ exports.assertion = function (selector, count) {
|
|||
}
|
||||
this.command = function (cb) {
|
||||
const self = this
|
||||
return this.api.execute(function (selector) {
|
||||
return document.querySelectorAll(selector).length
|
||||
}, [selector], function (res) {
|
||||
cb.call(self, res)
|
||||
})
|
||||
return this.api.execute(
|
||||
function (selector) {
|
||||
return document.querySelectorAll(selector).length
|
||||
},
|
||||
[selector],
|
||||
function (res) {
|
||||
cb.call(self, res)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ module.exports = {
|
|||
host: '127.0.0.1',
|
||||
port: 4444,
|
||||
cli_args: {
|
||||
'webdriver.chrome.driver': require('chromedriver').path
|
||||
}
|
||||
'webdriver.chrome.driver': require('chromedriver').path,
|
||||
},
|
||||
},
|
||||
|
||||
test_settings: {
|
||||
|
|
@ -23,24 +23,25 @@ module.exports = {
|
|||
selenium_host: 'localhost',
|
||||
silent: true,
|
||||
globals: {
|
||||
devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
|
||||
}
|
||||
devServerURL:
|
||||
'http://localhost:' + (process.env.PORT || config.dev.port),
|
||||
},
|
||||
},
|
||||
|
||||
chrome: {
|
||||
desiredCapabilities: {
|
||||
browserName: 'chrome',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true
|
||||
}
|
||||
acceptSslCerts: true,
|
||||
},
|
||||
},
|
||||
|
||||
firefox: {
|
||||
desiredCapabilities: {
|
||||
browserName: 'firefox',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true
|
||||
}
|
||||
}
|
||||
}
|
||||
acceptSslCerts: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ if (opts.indexOf('--env') === -1) {
|
|||
}
|
||||
|
||||
const spawn = require('cross-spawn')
|
||||
const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
|
||||
const runner = spawn('./node_modules/.bin/nightwatch', opts, {
|
||||
stdio: 'inherit',
|
||||
})
|
||||
|
||||
runner.on('exit', function (code) {
|
||||
server.close()
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@ module.exports = {
|
|||
.assert.containsText('h1', 'Welcome to Your Vue.js App')
|
||||
.assert.elementCount('img', 1)
|
||||
.end()
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
|||
2059
test/fixtures/mastoapi.json
vendored
2059
test/fixtures/mastoapi.json
vendored
File diff suppressed because it is too large
Load diff
42
test/fixtures/mock_api.js
vendored
42
test/fixtures/mock_api.js
vendored
|
|
@ -17,8 +17,8 @@ export const injectMswToTest = (defaultHandlers) => {
|
|||
worker.stop()
|
||||
},
|
||||
{
|
||||
auto: true
|
||||
}
|
||||
auto: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
|
@ -29,34 +29,44 @@ export const authApis = [
|
|||
http.post(`${testServer}/api/v1/apps`, () => {
|
||||
return HttpResponse.json({
|
||||
client_id: 'test-id',
|
||||
client_secret: 'test-secret'
|
||||
client_secret: 'test-secret',
|
||||
})
|
||||
}),
|
||||
http.get(`${testServer}/api/v1/apps/verify_credentials`, ({ request }) => {
|
||||
const authHeader = request.headers.get('Authorization')
|
||||
if (authHeader === 'Bearer test-app-token' ||
|
||||
authHeader === 'Bearer also-good-app-token') {
|
||||
if (
|
||||
authHeader === 'Bearer test-app-token' ||
|
||||
authHeader === 'Bearer also-good-app-token'
|
||||
) {
|
||||
return HttpResponse.json({})
|
||||
} else {
|
||||
// Pleroma 2.9.0 gives the following respoonse upon error
|
||||
return HttpResponse.json({ error: { detail: 'Internal server error' } }, {
|
||||
status: 400
|
||||
})
|
||||
return HttpResponse.json(
|
||||
{ error: { detail: 'Internal server error' } },
|
||||
{
|
||||
status: 400,
|
||||
},
|
||||
)
|
||||
}
|
||||
}),
|
||||
http.post(`${testServer}/oauth/token`, async ({ request }) => {
|
||||
const data = await request.formData()
|
||||
|
||||
if (data.get('client_id') === 'test-id' &&
|
||||
data.get('client_secret') === 'test-secret' &&
|
||||
data.get('grant_type') === 'client_credentials' &&
|
||||
data.has('redirect_uri')) {
|
||||
if (
|
||||
data.get('client_id') === 'test-id' &&
|
||||
data.get('client_secret') === 'test-secret' &&
|
||||
data.get('grant_type') === 'client_credentials' &&
|
||||
data.has('redirect_uri')
|
||||
) {
|
||||
return HttpResponse.json({ access_token: 'test-app-token' })
|
||||
} else {
|
||||
// Pleroma 2.9.0 gives the following respoonse upon error
|
||||
return HttpResponse.json({ error: 'Invalid credentials' }, {
|
||||
status: 400
|
||||
})
|
||||
return HttpResponse.json(
|
||||
{ error: 'Invalid credentials' },
|
||||
{
|
||||
status: 400,
|
||||
},
|
||||
)
|
||||
}
|
||||
})
|
||||
}),
|
||||
]
|
||||
|
|
|
|||
2
test/fixtures/mock_store.js
vendored
2
test/fixtures/mock_store.js
vendored
|
|
@ -2,7 +2,7 @@ import { createStore } from 'vuex'
|
|||
import { cloneDeep } from 'lodash'
|
||||
import vuexModules from 'src/modules/index.js'
|
||||
|
||||
const tweakModules = modules => {
|
||||
const tweakModules = (modules) => {
|
||||
const res = {}
|
||||
Object.entries(modules).forEach(([name, module]) => {
|
||||
const m = { ...module }
|
||||
|
|
|
|||
74
test/fixtures/setup_test.js
vendored
74
test/fixtures/setup_test.js
vendored
|
|
@ -4,8 +4,8 @@ import VueVirtualScroller from 'vue-virtual-scroller'
|
|||
import routes from 'src/boot/routes'
|
||||
import makeMockStore from './mock_store'
|
||||
|
||||
export const $t = msg => msg
|
||||
const $i18n = { t: msg => msg }
|
||||
export const $t = (msg) => msg
|
||||
const $i18n = { t: (msg) => msg }
|
||||
|
||||
const applyAfterStore = (store, afterStore) => {
|
||||
afterStore(store)
|
||||
|
|
@ -19,17 +19,20 @@ const getDefaultOpts = ({ afterStore = () => {} } = {}) => ({
|
|||
VueVirtualScroller,
|
||||
createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes: routes({ state: {
|
||||
users: {
|
||||
currentUser: {}
|
||||
routes: routes({
|
||||
state: {
|
||||
users: {
|
||||
currentUser: {},
|
||||
},
|
||||
instance: {},
|
||||
},
|
||||
instance: {}
|
||||
}})
|
||||
}),
|
||||
}),
|
||||
(Vue) => { Vue.directive('body-scroll-lock', {}) }
|
||||
(Vue) => {
|
||||
Vue.directive('body-scroll-lock', {})
|
||||
},
|
||||
],
|
||||
components: {
|
||||
},
|
||||
components: {},
|
||||
stubs: {
|
||||
I18nT: true,
|
||||
teleport: true,
|
||||
|
|
@ -38,23 +41,23 @@ const getDefaultOpts = ({ afterStore = () => {} } = {}) => ({
|
|||
},
|
||||
mocks: {
|
||||
$t,
|
||||
$i18n
|
||||
}
|
||||
}
|
||||
$i18n,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// https://github.com/vuejs/vue-test-utils/issues/960
|
||||
const customBehaviors = () => {
|
||||
const filterByText = keyword => {
|
||||
const match = keyword instanceof RegExp
|
||||
? (target) => target && keyword.test(target)
|
||||
: (target) => keyword === target
|
||||
const filterByText = (keyword) => {
|
||||
const match =
|
||||
keyword instanceof RegExp
|
||||
? (target) => target && keyword.test(target)
|
||||
: (target) => keyword === target
|
||||
|
||||
return wrapper => (
|
||||
return (wrapper) =>
|
||||
match(wrapper.text()) ||
|
||||
match(wrapper.attributes('aria-label')) ||
|
||||
match(wrapper.attributes('title'))
|
||||
)
|
||||
match(wrapper.attributes('aria-label')) ||
|
||||
match(wrapper.attributes('title'))
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -64,12 +67,10 @@ const customBehaviors = () => {
|
|||
.at(0)
|
||||
},
|
||||
findByText(searchedElement, text) {
|
||||
return this.findAll(searchedElement)
|
||||
.filter(filterByText(text))
|
||||
.at(0)
|
||||
return this.findAll(searchedElement).filter(filterByText(text)).at(0)
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
config.plugins.VueWrapper.install(customBehaviors)
|
||||
|
||||
|
|
@ -79,12 +80,14 @@ export const mountOpts = (allOpts = {}) => {
|
|||
const mergedOpts = {
|
||||
...opts,
|
||||
global: {
|
||||
...defaultOpts.global
|
||||
}
|
||||
...defaultOpts.global,
|
||||
},
|
||||
}
|
||||
|
||||
if (opts.global) {
|
||||
mergedOpts.global.plugins = mergedOpts.global.plugins.concat(opts.global.plugins || [])
|
||||
mergedOpts.global.plugins = mergedOpts.global.plugins.concat(
|
||||
opts.global.plugins || [],
|
||||
)
|
||||
Object.entries(opts.global).forEach(([k, v]) => {
|
||||
if (k === 'plugins') {
|
||||
return
|
||||
|
|
@ -104,10 +107,11 @@ export const mountOpts = (allOpts = {}) => {
|
|||
}
|
||||
|
||||
// https://stackoverflow.com/questions/78033718/how-can-i-wait-for-an-emitted-event-of-a-mounted-component-in-vue-test-utils
|
||||
export const waitForEvent = (wrapper, event, {
|
||||
timeout = 1000,
|
||||
timesEmitted = 1
|
||||
} = {}) => {
|
||||
export const waitForEvent = (
|
||||
wrapper,
|
||||
event,
|
||||
{ timeout = 1000, timesEmitted = 1 } = {},
|
||||
) => {
|
||||
const tick = 10
|
||||
|
||||
return vi.waitFor(
|
||||
|
|
@ -120,7 +124,7 @@ export const waitForEvent = (wrapper, event, {
|
|||
},
|
||||
{
|
||||
timeout,
|
||||
interval: tick
|
||||
}
|
||||
interval: tick,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
36
test/fixtures/statuses.json
vendored
36
test/fixtures/statuses.json
vendored
|
|
@ -144,9 +144,7 @@
|
|||
"external_url": "https:\/\/sealion.club\/notice\/957950",
|
||||
"in_reply_to_profileurl": "https:\/\/shitposter.club\/moonman",
|
||||
"in_reply_to_ostatus_uri": "https:\/\/shitposter.club\/user\/1",
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 0,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": false,
|
||||
|
|
@ -229,9 +227,7 @@
|
|||
"external_url": "https:\/\/soykaf.com\/notice\/339506",
|
||||
"in_reply_to_profileurl": null,
|
||||
"in_reply_to_ostatus_uri": null,
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 0,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": true,
|
||||
|
|
@ -629,9 +625,7 @@
|
|||
"external_url": "https:\/\/soykaf.com\/notice\/339502",
|
||||
"in_reply_to_profileurl": "https:\/\/gs.smuglo.li\/jimrusell01",
|
||||
"in_reply_to_ostatus_uri": "https:\/\/gs.smuglo.li\/user\/1987",
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 0,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": false,
|
||||
|
|
@ -806,9 +800,7 @@
|
|||
"external_url": "https:\/\/status.akionux.net\/notice\/359563",
|
||||
"in_reply_to_profileurl": null,
|
||||
"in_reply_to_ostatus_uri": null,
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 0,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": true,
|
||||
|
|
@ -975,9 +967,7 @@
|
|||
"external_url": "https:\/\/gs.smuglo.li\/notice\/589590",
|
||||
"in_reply_to_profileurl": null,
|
||||
"in_reply_to_ostatus_uri": null,
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 0,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": true,
|
||||
|
|
@ -1046,9 +1036,7 @@
|
|||
"external_url": "https:\/\/shitposter.club\/notice\/773502",
|
||||
"in_reply_to_profileurl": "https:\/\/gs.smuglo.li\/jimrusell01",
|
||||
"in_reply_to_ostatus_uri": "https:\/\/gs.smuglo.li\/user\/1987",
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 0,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": false,
|
||||
|
|
@ -1131,9 +1119,7 @@
|
|||
"external_url": "https:\/\/gs.smuglo.li\/notice\/589587",
|
||||
"in_reply_to_profileurl": null,
|
||||
"in_reply_to_ostatus_uri": null,
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 2,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": true,
|
||||
|
|
@ -1224,9 +1210,7 @@
|
|||
"external_url": "https:\/\/shitposter.club\/notice\/773500",
|
||||
"in_reply_to_profileurl": null,
|
||||
"in_reply_to_ostatus_uri": null,
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 0,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": true,
|
||||
|
|
@ -1561,9 +1545,7 @@
|
|||
"external_url": "https:\/\/soykaf.com\/notice\/339493",
|
||||
"in_reply_to_profileurl": null,
|
||||
"in_reply_to_ostatus_uri": null,
|
||||
"attentions": [
|
||||
|
||||
],
|
||||
"attentions": [],
|
||||
"fave_num": 0,
|
||||
"repeat_num": 0,
|
||||
"is_post_verb": true,
|
||||
|
|
|
|||
|
|
@ -4,14 +4,14 @@ import { createStore } from 'vuex'
|
|||
|
||||
const store = createStore({
|
||||
state: {
|
||||
instance: {}
|
||||
}
|
||||
instance: {},
|
||||
},
|
||||
})
|
||||
|
||||
describe('routes', () => {
|
||||
const router = createRouter({
|
||||
history: createMemoryHistory(),
|
||||
routes: routes(store)
|
||||
routes: routes(store),
|
||||
})
|
||||
|
||||
it('root path', async () => {
|
||||
|
|
@ -20,25 +20,40 @@ describe('routes', () => {
|
|||
const matchedComponents = router.currentRoute.value.matched
|
||||
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
expect(Object.hasOwn(matchedComponents[0].components.default.components, 'Timeline')).to.eql(true)
|
||||
expect(
|
||||
Object.hasOwn(
|
||||
matchedComponents[0].components.default.components,
|
||||
'Timeline',
|
||||
),
|
||||
).to.eql(true)
|
||||
})
|
||||
|
||||
it('user\'s profile', async () => {
|
||||
it("user's profile", async () => {
|
||||
await router.push('/fake-user-name')
|
||||
|
||||
const matchedComponents = router.currentRoute.value.matched
|
||||
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
expect(Object.hasOwn(matchedComponents[0].components.default.components, 'UserCard')).to.eql(true)
|
||||
expect(
|
||||
Object.hasOwn(
|
||||
matchedComponents[0].components.default.components,
|
||||
'UserCard',
|
||||
),
|
||||
).to.eql(true)
|
||||
})
|
||||
|
||||
it('user\'s profile at /users', async () => {
|
||||
it("user's profile at /users", async () => {
|
||||
await router.push('/users/fake-user-name')
|
||||
|
||||
const matchedComponents = router.currentRoute.value.matched
|
||||
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
expect(Object.hasOwn(matchedComponents[0].components.default.components, 'UserCard')).to.eql(true)
|
||||
expect(
|
||||
Object.hasOwn(
|
||||
matchedComponents[0].components.default.components,
|
||||
'UserCard',
|
||||
),
|
||||
).to.eql(true)
|
||||
})
|
||||
|
||||
it('list view', async () => {
|
||||
|
|
@ -46,7 +61,12 @@ describe('routes', () => {
|
|||
|
||||
const matchedComponents = router.currentRoute.value.matched
|
||||
|
||||
expect(Object.hasOwn(matchedComponents[0].components.default.components, 'ListsCard')).to.eql(true)
|
||||
expect(
|
||||
Object.hasOwn(
|
||||
matchedComponents[0].components.default.components,
|
||||
'ListsCard',
|
||||
),
|
||||
).to.eql(true)
|
||||
})
|
||||
|
||||
it('list timeline', async () => {
|
||||
|
|
@ -54,7 +74,12 @@ describe('routes', () => {
|
|||
|
||||
const matchedComponents = router.currentRoute.value.matched
|
||||
|
||||
expect(Object.hasOwn(matchedComponents[0].components.default.components, 'Timeline')).to.eql(true)
|
||||
expect(
|
||||
Object.hasOwn(
|
||||
matchedComponents[0].components.default.components,
|
||||
'Timeline',
|
||||
),
|
||||
).to.eql(true)
|
||||
})
|
||||
|
||||
it('list edit', async () => {
|
||||
|
|
@ -62,6 +87,11 @@ describe('routes', () => {
|
|||
|
||||
const matchedComponents = router.currentRoute.value.matched
|
||||
|
||||
expect(Object.hasOwn(matchedComponents[0].components.default.components, 'BasicUserCard')).to.eql(true)
|
||||
expect(
|
||||
Object.hasOwn(
|
||||
matchedComponents[0].components.default.components,
|
||||
'BasicUserCard',
|
||||
),
|
||||
).to.eql(true)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -14,10 +14,16 @@ const autoSaveOrNot = (caseFn, caseTitle, runFn) => {
|
|||
}
|
||||
|
||||
const saveManually = async (wrapper) => {
|
||||
const morePostActions = wrapper.findByText('button', $t('post_status.more_post_actions'))
|
||||
const morePostActions = wrapper.findByText(
|
||||
'button',
|
||||
$t('post_status.more_post_actions'),
|
||||
)
|
||||
await morePostActions.trigger('click')
|
||||
|
||||
const btn = wrapper.findByText('button', $t('post_status.save_to_drafts_button'))
|
||||
const btn = wrapper.findByText(
|
||||
'button',
|
||||
$t('post_status.save_to_drafts_button'),
|
||||
)
|
||||
await btn.trigger('click')
|
||||
}
|
||||
|
||||
|
|
@ -28,28 +34,34 @@ afterEach(() => {
|
|||
})
|
||||
|
||||
describe('Draft saving', () => {
|
||||
autoSaveOrNot(it, 'should save when the button is clicked', async (autoSave) => {
|
||||
const wrapper = mount(PostStatusForm, mountOpts())
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'autoSaveDraft',
|
||||
value: autoSave
|
||||
})
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(0)
|
||||
autoSaveOrNot(
|
||||
it,
|
||||
'should save when the button is clicked',
|
||||
async (autoSave) => {
|
||||
const wrapper = mount(PostStatusForm, mountOpts())
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'autoSaveDraft',
|
||||
value: autoSave,
|
||||
})
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(0)
|
||||
|
||||
const textarea = wrapper.get('textarea')
|
||||
await textarea.setValue('mew mew')
|
||||
const textarea = wrapper.get('textarea')
|
||||
await textarea.setValue('mew mew')
|
||||
|
||||
await saveManually(wrapper)
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(1)
|
||||
expect(wrapper.vm.$store.getters.draftsArray[0].status).to.equal('mew mew')
|
||||
})
|
||||
await saveManually(wrapper)
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(1)
|
||||
expect(wrapper.vm.$store.getters.draftsArray[0].status).to.equal(
|
||||
'mew mew',
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
it('should auto-save if it is enabled', async function () {
|
||||
vi.useFakeTimers()
|
||||
const wrapper = mount(PostStatusForm, mountOpts())
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'autoSaveDraft',
|
||||
value: true
|
||||
value: true,
|
||||
})
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(0)
|
||||
const textarea = wrapper.get('textarea')
|
||||
|
|
@ -62,14 +74,17 @@ describe('Draft saving', () => {
|
|||
})
|
||||
|
||||
it('should auto-save when close if auto-save is on', async () => {
|
||||
const wrapper = mount(PostStatusForm, mountOpts({
|
||||
props: {
|
||||
closeable: true
|
||||
}
|
||||
}))
|
||||
const wrapper = mount(
|
||||
PostStatusForm,
|
||||
mountOpts({
|
||||
props: {
|
||||
closeable: true,
|
||||
},
|
||||
}),
|
||||
)
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'autoSaveDraft',
|
||||
value: true
|
||||
value: true,
|
||||
})
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(0)
|
||||
const textarea = wrapper.get('textarea')
|
||||
|
|
@ -80,18 +95,21 @@ describe('Draft saving', () => {
|
|||
})
|
||||
|
||||
it('should save when close if auto-save is off, and unsavedPostAction is save', async () => {
|
||||
const wrapper = mount(PostStatusForm, mountOpts({
|
||||
props: {
|
||||
closeable: true
|
||||
}
|
||||
}))
|
||||
const wrapper = mount(
|
||||
PostStatusForm,
|
||||
mountOpts({
|
||||
props: {
|
||||
closeable: true,
|
||||
},
|
||||
}),
|
||||
)
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'autoSaveDraft',
|
||||
value: false
|
||||
value: false,
|
||||
})
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'unsavedPostAction',
|
||||
value: 'save'
|
||||
value: 'save',
|
||||
})
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(0)
|
||||
const textarea = wrapper.get('textarea')
|
||||
|
|
@ -102,18 +120,21 @@ describe('Draft saving', () => {
|
|||
})
|
||||
|
||||
it('should discard when close if auto-save is off, and unsavedPostAction is discard', async () => {
|
||||
const wrapper = mount(PostStatusForm, mountOpts({
|
||||
props: {
|
||||
closeable: true
|
||||
}
|
||||
}))
|
||||
const wrapper = mount(
|
||||
PostStatusForm,
|
||||
mountOpts({
|
||||
props: {
|
||||
closeable: true,
|
||||
},
|
||||
}),
|
||||
)
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'autoSaveDraft',
|
||||
value: false
|
||||
value: false,
|
||||
})
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'unsavedPostAction',
|
||||
value: 'discard'
|
||||
value: 'discard',
|
||||
})
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(0)
|
||||
const textarea = wrapper.get('textarea')
|
||||
|
|
@ -124,25 +145,31 @@ describe('Draft saving', () => {
|
|||
})
|
||||
|
||||
it('should confirm when close if auto-save is off, and unsavedPostAction is confirm', async () => {
|
||||
const wrapper = mount(PostStatusForm, mountOpts({
|
||||
props: {
|
||||
closeable: true
|
||||
}
|
||||
}))
|
||||
const wrapper = mount(
|
||||
PostStatusForm,
|
||||
mountOpts({
|
||||
props: {
|
||||
closeable: true,
|
||||
},
|
||||
}),
|
||||
)
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'autoSaveDraft',
|
||||
value: false
|
||||
value: false,
|
||||
})
|
||||
await wrapper.vm.$store.dispatch('setOption', {
|
||||
name: 'unsavedPostAction',
|
||||
value: 'confirm'
|
||||
value: 'confirm',
|
||||
})
|
||||
expect(wrapper.vm.$store.getters.draftCount).to.equal(0)
|
||||
const textarea = wrapper.get('textarea')
|
||||
await textarea.setValue('mew mew')
|
||||
wrapper.vm.requestClose()
|
||||
await nextTick()
|
||||
const saveButton = wrapper.findByText('button', $t('post_status.close_confirm_save_button'))
|
||||
const saveButton = wrapper.findByText(
|
||||
'button',
|
||||
$t('post_status.close_confirm_save_button'),
|
||||
)
|
||||
expect(saveButton).to.be.ok
|
||||
await saveButton.trigger('click')
|
||||
console.info('clicked')
|
||||
|
|
|
|||
|
|
@ -11,33 +11,33 @@ const generateInput = (value, padEmoji = true) => {
|
|||
$store: {
|
||||
getters: {
|
||||
mergedConfig: {
|
||||
padEmoji
|
||||
}
|
||||
}
|
||||
padEmoji,
|
||||
},
|
||||
},
|
||||
},
|
||||
$t: (msg) => msg
|
||||
$t: (msg) => msg,
|
||||
},
|
||||
stubs: {
|
||||
FAIcon: true,
|
||||
Popover: {
|
||||
template: `<div><slot trigger /></div>`,
|
||||
methods: {
|
||||
updateStyles () {}
|
||||
}
|
||||
}
|
||||
updateStyles() {},
|
||||
},
|
||||
},
|
||||
},
|
||||
directives: {
|
||||
'click-outside': vClickOutside
|
||||
}
|
||||
'click-outside': vClickOutside,
|
||||
},
|
||||
},
|
||||
props: {
|
||||
suggest: () => [],
|
||||
enableEmojiPicker: true,
|
||||
modelValue: value
|
||||
modelValue: value,
|
||||
},
|
||||
slots: {
|
||||
default: () => h('input', '')
|
||||
}
|
||||
default: () => h('input', ''),
|
||||
},
|
||||
})
|
||||
return wrapper
|
||||
}
|
||||
|
|
@ -85,7 +85,9 @@ describe('EmojiInput', () => {
|
|||
wrapper.setData({ caret: 6 })
|
||||
wrapper.vm.insert({ insertion: ':ebin:', keepOpen: false })
|
||||
const inputEvents = wrapper.emitted()['update:modelValue']
|
||||
expect(inputEvents[inputEvents.length - 1][0]).to.eql('Spurdo :ebin: Sparde')
|
||||
expect(inputEvents[inputEvents.length - 1][0]).to.eql(
|
||||
'Spurdo :ebin: Sparde',
|
||||
)
|
||||
})
|
||||
|
||||
it('inserts string between words without creating extra spaces (other caret)', () => {
|
||||
|
|
@ -96,7 +98,9 @@ describe('EmojiInput', () => {
|
|||
wrapper.setData({ caret: 7 })
|
||||
wrapper.vm.insert({ insertion: ':ebin:', keepOpen: false })
|
||||
const inputEvents = wrapper.emitted()['update:modelValue']
|
||||
expect(inputEvents[inputEvents.length - 1][0]).to.eql('Spurdo :ebin: Sparde')
|
||||
expect(inputEvents[inputEvents.length - 1][0]).to.eql(
|
||||
'Spurdo :ebin: Sparde',
|
||||
)
|
||||
})
|
||||
|
||||
it('inserts string without any padding if padEmoji setting is set to false', () => {
|
||||
|
|
@ -107,7 +111,9 @@ describe('EmojiInput', () => {
|
|||
wrapper.setData({ caret: initialString.length, keepOpen: false })
|
||||
wrapper.vm.insert({ insertion: ':spam:' })
|
||||
const inputEvents = wrapper.emitted()['update:modelValue']
|
||||
expect(inputEvents[inputEvents.length - 1][0]).to.eql('Eat some spam!:spam:')
|
||||
expect(inputEvents[inputEvents.length - 1][0]).to.eql(
|
||||
'Eat some spam!:spam:',
|
||||
)
|
||||
})
|
||||
|
||||
it('correctly sets caret after insertion at beginning', async () => {
|
||||
|
|
|
|||
|
|
@ -21,53 +21,44 @@ describe('Gallery', () => {
|
|||
|
||||
it('one audio attachment', () => {
|
||||
local = {
|
||||
attachments: [
|
||||
{ mimetype: 'audio/mpeg' }
|
||||
]
|
||||
attachments: [{ mimetype: 'audio/mpeg' }],
|
||||
}
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] }
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
])
|
||||
})
|
||||
|
||||
it('one image attachment', () => {
|
||||
local = {
|
||||
attachments: [
|
||||
{ mimetype: 'image/png' }
|
||||
]
|
||||
attachments: [{ mimetype: 'image/png' }],
|
||||
}
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ items: [{ mimetype: 'image/png' }] }
|
||||
{ items: [{ mimetype: 'image/png' }] },
|
||||
])
|
||||
})
|
||||
|
||||
it('one audio attachment and one image attachment', () => {
|
||||
local = {
|
||||
attachments: [
|
||||
{ mimetype: 'audio/mpeg' },
|
||||
{ mimetype: 'image/png' }
|
||||
]
|
||||
attachments: [{ mimetype: 'audio/mpeg' }, { mimetype: 'image/png' }],
|
||||
}
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
{ items: [{ mimetype: 'image/png' }] }
|
||||
{ items: [{ mimetype: 'image/png' }] },
|
||||
])
|
||||
})
|
||||
|
||||
it('has "size" key set to "hide"', () => {
|
||||
let local
|
||||
local = {
|
||||
attachments: [
|
||||
{ mimetype: 'audio/mpeg' }
|
||||
],
|
||||
size: 'hide'
|
||||
attachments: [{ mimetype: 'audio/mpeg' }],
|
||||
size: 'hide',
|
||||
}
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ minimal: true, items: [{ mimetype: 'audio/mpeg' }] }
|
||||
{ minimal: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
])
|
||||
|
||||
local = {
|
||||
|
|
@ -80,9 +71,9 @@ describe('Gallery', () => {
|
|||
{ mimetype: 'audio/mpeg' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' }
|
||||
{ mimetype: 'image/jpg' },
|
||||
],
|
||||
size: 'hide'
|
||||
size: 'hide',
|
||||
}
|
||||
|
||||
// When defining `size: hide`, the `items` aren't
|
||||
|
|
@ -96,7 +87,7 @@ describe('Gallery', () => {
|
|||
{ minimal: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
{ minimal: true, items: [{ mimetype: 'image/jpg' }] },
|
||||
{ minimal: true, items: [{ mimetype: 'image/png' }] },
|
||||
{ minimal: true, items: [{ mimetype: 'image/jpg' }] }
|
||||
{ minimal: true, items: [{ mimetype: 'image/jpg' }] },
|
||||
])
|
||||
})
|
||||
|
||||
|
|
@ -104,12 +95,10 @@ describe('Gallery', () => {
|
|||
it('non-image/audio', () => {
|
||||
let local
|
||||
local = {
|
||||
attachments: [
|
||||
{ mimetype: 'plain/text' }
|
||||
]
|
||||
attachments: [{ mimetype: 'plain/text' }],
|
||||
}
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ minimal: true, items: [{ mimetype: 'plain/text' }] }
|
||||
{ minimal: true, items: [{ mimetype: 'plain/text' }] },
|
||||
])
|
||||
|
||||
// No grouping of non-image/audio items
|
||||
|
|
@ -117,13 +106,13 @@ describe('Gallery', () => {
|
|||
attachments: [
|
||||
{ mimetype: 'plain/text' },
|
||||
{ mimetype: 'plain/text' },
|
||||
{ mimetype: 'plain/text' }
|
||||
]
|
||||
{ mimetype: 'plain/text' },
|
||||
],
|
||||
}
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ minimal: true, items: [{ mimetype: 'plain/text' }] },
|
||||
{ minimal: true, items: [{ mimetype: 'plain/text' }] },
|
||||
{ minimal: true, items: [{ mimetype: 'plain/text' }] }
|
||||
{ minimal: true, items: [{ mimetype: 'plain/text' }] },
|
||||
])
|
||||
|
||||
local = {
|
||||
|
|
@ -131,8 +120,8 @@ describe('Gallery', () => {
|
|||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'plain/text' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'audio/mpeg' }
|
||||
]
|
||||
{ mimetype: 'audio/mpeg' },
|
||||
],
|
||||
}
|
||||
// NOTE / TODO: When defining `size: hide`, the `items` aren't
|
||||
// grouped and `audio` isn't set
|
||||
|
|
@ -140,7 +129,7 @@ describe('Gallery', () => {
|
|||
{ items: [{ mimetype: 'image/png' }] },
|
||||
{ minimal: true, items: [{ mimetype: 'plain/text' }] },
|
||||
{ items: [{ mimetype: 'image/jpg' }] },
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] }
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
])
|
||||
})
|
||||
|
||||
|
|
@ -153,15 +142,22 @@ describe('Gallery', () => {
|
|||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/jpg' }
|
||||
]
|
||||
{ mimetype: 'image/jpg' },
|
||||
],
|
||||
}
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
{ items: [{ mimetype: 'image/png' }] },
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
{ items: [{ mimetype: 'image/jpg' }, { mimetype: 'image/png' }, { mimetype: 'image/jpg' }, { mimetype: 'image/jpg' }] }
|
||||
{
|
||||
items: [
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
local = {
|
||||
|
|
@ -172,16 +168,22 @@ describe('Gallery', () => {
|
|||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'audio/mpeg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'audio/mpeg' }
|
||||
]
|
||||
{ mimetype: 'audio/mpeg' },
|
||||
],
|
||||
}
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ items: [{ mimetype: 'image/jpg' }, { mimetype: 'image/png' }, { mimetype: 'image/jpg' }] },
|
||||
{
|
||||
items: [
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
],
|
||||
},
|
||||
{ items: [{ mimetype: 'image/jpg' }] },
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
{ items: [{ mimetype: 'image/png' }] },
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] }
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
])
|
||||
|
||||
local = {
|
||||
|
|
@ -192,15 +194,28 @@ describe('Gallery', () => {
|
|||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' }
|
||||
]
|
||||
{ mimetype: 'image/jpg' },
|
||||
],
|
||||
}
|
||||
|
||||
// Group by three-per-row, unless there's one dangling, then stick it on the end of the last row
|
||||
// https://git.pleroma.social/pleroma/pleroma-fe/-/merge_requests/1785#note_98514
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ items: [{ mimetype: 'image/jpg' }, { mimetype: 'image/png' }, { mimetype: 'image/jpg' }] },
|
||||
{ items: [{ mimetype: 'image/jpg' }, { mimetype: 'image/png' }, { mimetype: 'image/png' }, { mimetype: 'image/jpg' }] }
|
||||
{
|
||||
items: [
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
],
|
||||
},
|
||||
])
|
||||
|
||||
local = {
|
||||
|
|
@ -212,14 +227,26 @@ describe('Gallery', () => {
|
|||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' }
|
||||
]
|
||||
{ mimetype: 'image/png' },
|
||||
],
|
||||
}
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ items: [{ mimetype: 'image/jpg' }, { mimetype: 'image/png' }, { mimetype: 'image/jpg' }] },
|
||||
{ items: [{ mimetype: 'image/jpg' }, { mimetype: 'image/png' }, { mimetype: 'image/png' }] },
|
||||
{ items: [{ mimetype: 'image/jpg' }, { mimetype: 'image/png' }] }
|
||||
{
|
||||
items: [
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
],
|
||||
},
|
||||
{
|
||||
items: [
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/png' },
|
||||
],
|
||||
},
|
||||
{ items: [{ mimetype: 'image/jpg' }, { mimetype: 'image/png' }] },
|
||||
])
|
||||
})
|
||||
|
||||
|
|
@ -231,13 +258,13 @@ describe('Gallery', () => {
|
|||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'image/jpg' }
|
||||
{ mimetype: 'image/jpg' },
|
||||
]
|
||||
|
||||
local = { grid: true, attachments }
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ grid: true, items: attachments }
|
||||
{ grid: true, items: attachments },
|
||||
])
|
||||
})
|
||||
|
||||
|
|
@ -247,7 +274,7 @@ describe('Gallery', () => {
|
|||
{ mimetype: 'image/png' },
|
||||
{ mimetype: 'image/jpg' },
|
||||
{ mimetype: 'audio/mpeg' },
|
||||
{ mimetype: 'image/jpg' }
|
||||
{ mimetype: 'image/jpg' },
|
||||
]
|
||||
|
||||
let local
|
||||
|
|
@ -255,14 +282,14 @@ describe('Gallery', () => {
|
|||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
{ items: [{ mimetype: 'image/png' }] }
|
||||
{ items: [{ mimetype: 'image/png' }] },
|
||||
])
|
||||
|
||||
local = { attachments, limit: 3 }
|
||||
|
||||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
{ items: [{ mimetype: 'image/png' }, { mimetype: 'image/jpg' }] }
|
||||
{ items: [{ mimetype: 'image/png' }, { mimetype: 'image/jpg' }] },
|
||||
])
|
||||
|
||||
local = { attachments, limit: 4 }
|
||||
|
|
@ -270,7 +297,7 @@ describe('Gallery', () => {
|
|||
expect(Gallery.computed.rows.call(local)).to.eql([
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
{ items: [{ mimetype: 'image/png' }, { mimetype: 'image/jpg' }] },
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] }
|
||||
{ audio: true, items: [{ mimetype: 'audio/mpeg' }] },
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,15 +8,15 @@ const global = {
|
|||
state: {},
|
||||
getters: {
|
||||
mergedConfig: () => ({
|
||||
mentionLinkShowTooltip: true
|
||||
mentionLinkShowTooltip: true,
|
||||
}),
|
||||
findUserByUrl: () => null
|
||||
}
|
||||
}
|
||||
findUserByUrl: () => null,
|
||||
},
|
||||
},
|
||||
},
|
||||
stubs: {
|
||||
FAIcon: true
|
||||
}
|
||||
FAIcon: true,
|
||||
},
|
||||
}
|
||||
|
||||
const makeMention = (who, noClass) => {
|
||||
|
|
@ -26,12 +26,14 @@ const makeMention = (who, noClass) => {
|
|||
: `<span class="h-card"><a class="u-url mention" href="https://fake.tld/@${who}">@<span>${who}</span></a></span>`
|
||||
}
|
||||
const p = (...data) => `<p>${data.join('')}</p>`
|
||||
const compwrap = (...data) => `<span class="RichContent">${data.join('')}</span>`
|
||||
const mentionsLine = (times) => [
|
||||
'<mentions-line-stub mentions="',
|
||||
new Array(times).fill('[object Object]').join(','),
|
||||
'"></mentions-line-stub>'
|
||||
].join('')
|
||||
const compwrap = (...data) =>
|
||||
`<span class="RichContent">${data.join('')}</span>`
|
||||
const mentionsLine = (times) =>
|
||||
[
|
||||
'<mentions-line-stub mentions="',
|
||||
new Array(times).fill('[object Object]').join(','),
|
||||
'"></mentions-line-stub>',
|
||||
].join('')
|
||||
|
||||
describe('RichContent', () => {
|
||||
it('renders simple post without exploding', () => {
|
||||
|
|
@ -43,22 +45,16 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(html))
|
||||
})
|
||||
|
||||
it('unescapes everything as needed', () => {
|
||||
const html = [
|
||||
p('Testing 'em all'),
|
||||
'Testing 'em all'
|
||||
].join('')
|
||||
const expected = [
|
||||
p('Testing \'em all'),
|
||||
'Testing \'em all'
|
||||
].join('')
|
||||
const html = [p('Testing 'em all'), 'Testing 'em all'].join('')
|
||||
const expected = [p("Testing 'em all"), "Testing 'em all"].join('')
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
global,
|
||||
props: {
|
||||
|
|
@ -66,18 +62,15 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(expected))
|
||||
})
|
||||
|
||||
it('replaces mention with mentionsline', () => {
|
||||
const html = p(
|
||||
makeMention('John'),
|
||||
' how are you doing today?'
|
||||
)
|
||||
const html = p(makeMention('John'), ' how are you doing today?')
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
global,
|
||||
props: {
|
||||
|
|
@ -85,37 +78,30 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(p(
|
||||
mentionsLine(1),
|
||||
' how are you doing today?'
|
||||
)))
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(
|
||||
compwrap(p(mentionsLine(1), ' how are you doing today?')),
|
||||
)
|
||||
})
|
||||
|
||||
it('replaces mentions at the end of the hellpost', () => {
|
||||
const html = [
|
||||
p('How are you doing today, fine gentlemen?'),
|
||||
p(
|
||||
makeMention('John'),
|
||||
makeMention('Josh'),
|
||||
makeMention('Jeremy')
|
||||
)
|
||||
p(makeMention('John'), makeMention('Josh'), makeMention('Jeremy')),
|
||||
].join('')
|
||||
const expected = [
|
||||
p(
|
||||
'How are you doing today, fine gentlemen?'
|
||||
),
|
||||
p('How are you doing today, fine gentlemen?'),
|
||||
// TODO fix this extra line somehow?
|
||||
p(
|
||||
'<mentions-line-stub mentions="',
|
||||
'[object Object],',
|
||||
'[object Object],',
|
||||
'[object Object]',
|
||||
'"></mentions-line-stub>'
|
||||
)
|
||||
'"></mentions-line-stub>',
|
||||
),
|
||||
].join('')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
|
|
@ -125,8 +111,8 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(expected))
|
||||
|
|
@ -134,26 +120,24 @@ describe('RichContent', () => {
|
|||
|
||||
it('Does not touch links if link handling is disabled', () => {
|
||||
const html = [
|
||||
[
|
||||
makeMention('Jack'),
|
||||
'let\'s meet up with ',
|
||||
makeMention('Janet')
|
||||
].join(''),
|
||||
[
|
||||
makeMention('John'),
|
||||
makeMention('Josh'), makeMention('Jeremy')
|
||||
].join('')
|
||||
[makeMention('Jack'), "let's meet up with ", makeMention('Janet')].join(
|
||||
'',
|
||||
),
|
||||
[makeMention('John'), makeMention('Josh'), makeMention('Jeremy')].join(
|
||||
'',
|
||||
),
|
||||
].join('\n')
|
||||
const strippedHtml = [
|
||||
[
|
||||
makeMention('Jack', true),
|
||||
'let\'s meet up with ',
|
||||
makeMention('Janet', true)
|
||||
"let's meet up with ",
|
||||
makeMention('Janet', true),
|
||||
].join(''),
|
||||
[
|
||||
makeMention('John', true),
|
||||
makeMention('Josh', true), makeMention('Jeremy', true)
|
||||
].join('')
|
||||
makeMention('Josh', true),
|
||||
makeMention('Jeremy', true),
|
||||
].join(''),
|
||||
].join('\n')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
|
|
@ -163,21 +147,18 @@ describe('RichContent', () => {
|
|||
handleLinks: false,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html()).to.eql(compwrap(strippedHtml))
|
||||
})
|
||||
|
||||
it('Adds greentext and cyantext to the post', () => {
|
||||
const html = [
|
||||
'>preordering videogames',
|
||||
'>any year'
|
||||
].join('\n')
|
||||
const html = ['>preordering videogames', '>any year'].join('\n')
|
||||
const expected = [
|
||||
'<span class="greentext">>preordering videogames</span>',
|
||||
'<span class="greentext">>any year</span>'
|
||||
'<span class="greentext">>any year</span>',
|
||||
].join('\n')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
|
|
@ -187,18 +168,15 @@ describe('RichContent', () => {
|
|||
handleLinks: false,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html()).to.eql(compwrap(expected))
|
||||
})
|
||||
|
||||
it('Does not add greentext and cyantext if setting is set to false', () => {
|
||||
const html = [
|
||||
'>preordering videogames',
|
||||
'>any year'
|
||||
].join('\n')
|
||||
const html = ['>preordering videogames', '>any year'].join('\n')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
global,
|
||||
|
|
@ -207,8 +185,8 @@ describe('RichContent', () => {
|
|||
handleLinks: false,
|
||||
greentext: false,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html()).to.eql(compwrap(html))
|
||||
|
|
@ -218,7 +196,7 @@ describe('RichContent', () => {
|
|||
const html = p('Ebin :DDDD :spurdo:')
|
||||
const expected = p(
|
||||
'Ebin :DDDD ',
|
||||
'<anonymous-stub shortcode="spurdo" islocal="true" class="emoji img" src="about:blank" title=":spurdo:" alt=":spurdo:"></anonymous-stub>'
|
||||
'<anonymous-stub shortcode="spurdo" islocal="true" class="emoji img" src="about:blank" title=":spurdo:" alt=":spurdo:"></anonymous-stub>',
|
||||
)
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
|
|
@ -228,14 +206,14 @@ describe('RichContent', () => {
|
|||
handleLinks: false,
|
||||
greentext: false,
|
||||
emoji: [{ url: 'about:blank', shortcode: 'spurdo' }],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(expected))
|
||||
})
|
||||
|
||||
it('Doesn\'t add nonexistent emoji to post', () => {
|
||||
it("Doesn't add nonexistent emoji to post", () => {
|
||||
const html = p('Lol :lol:')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
|
|
@ -245,8 +223,8 @@ describe('RichContent', () => {
|
|||
handleLinks: false,
|
||||
greentext: false,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(html))
|
||||
|
|
@ -257,13 +235,13 @@ describe('RichContent', () => {
|
|||
'>quote',
|
||||
makeMention('lol'),
|
||||
'>quote',
|
||||
'>quote'
|
||||
'>quote',
|
||||
].join('\n')
|
||||
const expected = [
|
||||
'<span class="greentext">>quote</span>',
|
||||
mentionsLine(1),
|
||||
'<span class="greentext">>quote</span>',
|
||||
'<span class="greentext">>quote</span>'
|
||||
'<span class="greentext">>quote</span>',
|
||||
].join('\n')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
|
|
@ -273,8 +251,8 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html()).to.eql(compwrap(expected))
|
||||
|
|
@ -284,19 +262,10 @@ describe('RichContent', () => {
|
|||
const html = [
|
||||
'Bruh',
|
||||
'Bruh',
|
||||
[
|
||||
makeMention('foo'),
|
||||
makeMention('bar'),
|
||||
makeMention('baz')
|
||||
].join(''),
|
||||
'Bruh'
|
||||
].join('<br>')
|
||||
const expected = [
|
||||
[makeMention('foo'), makeMention('bar'), makeMention('baz')].join(''),
|
||||
'Bruh',
|
||||
'Bruh',
|
||||
mentionsLine(3),
|
||||
'Bruh'
|
||||
].join('<br>')
|
||||
const expected = ['Bruh', 'Bruh', mentionsLine(3), 'Bruh'].join('<br>')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
global,
|
||||
|
|
@ -305,8 +274,8 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(expected))
|
||||
|
|
@ -321,7 +290,7 @@ describe('RichContent', () => {
|
|||
'#nou</a>',
|
||||
' <a class="hashtag" data-tag="screencap" href="https://shitposter.club/tag/screencap">',
|
||||
'#screencap</a>',
|
||||
' </p>'
|
||||
' </p>',
|
||||
].join('')
|
||||
const expected = [
|
||||
'<p>',
|
||||
|
|
@ -331,7 +300,7 @@ describe('RichContent', () => {
|
|||
'</hashtag-link-stub>',
|
||||
' <hashtag-link-stub url="https://shitposter.club/tag/screencap" content="#screencap" tag="screencap">',
|
||||
'</hashtag-link-stub>',
|
||||
' </p>'
|
||||
' </p>',
|
||||
].join('')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
|
|
@ -341,8 +310,8 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(expected))
|
||||
|
|
@ -359,11 +328,9 @@ describe('RichContent', () => {
|
|||
'lol.tld/</span>',
|
||||
'<span>',
|
||||
'</span>',
|
||||
'</a>'
|
||||
'</a>',
|
||||
),
|
||||
p(
|
||||
'Testing'
|
||||
)
|
||||
p('Testing'),
|
||||
].join('')
|
||||
const expected = [
|
||||
p(
|
||||
|
|
@ -378,11 +345,9 @@ describe('RichContent', () => {
|
|||
'</span>',
|
||||
'</a>',
|
||||
'</span>',
|
||||
'</span>'
|
||||
'</span>',
|
||||
),
|
||||
p(
|
||||
'Testing'
|
||||
)
|
||||
p('Testing'),
|
||||
].join('')
|
||||
|
||||
const wrapper = mount(RichContent, {
|
||||
|
|
@ -392,11 +357,16 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '').replace(/<!--.*?-->/g, '')).to.eql(compwrap(expected))
|
||||
expect(
|
||||
wrapper
|
||||
.html()
|
||||
.replace(/\n/g, '')
|
||||
.replace(/<!--.*?-->/g, ''),
|
||||
).to.eql(compwrap(expected))
|
||||
})
|
||||
|
||||
it('rich contents of nested mentions are handled properly', () => {
|
||||
|
|
@ -422,7 +392,7 @@ describe('RichContent', () => {
|
|||
'</a>',
|
||||
' ',
|
||||
'</span>',
|
||||
'Testing'
|
||||
'Testing',
|
||||
].join('')
|
||||
const expected = [
|
||||
'<span>',
|
||||
|
|
@ -450,7 +420,7 @@ describe('RichContent', () => {
|
|||
'</span>',
|
||||
' ',
|
||||
'</span>',
|
||||
'Testing'
|
||||
'Testing',
|
||||
].join('')
|
||||
|
||||
const wrapper = mount(RichContent, {
|
||||
|
|
@ -460,11 +430,16 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '').replace(/<!--.*?-->/g, '')).to.eql(compwrap(expected))
|
||||
expect(
|
||||
wrapper
|
||||
.html()
|
||||
.replace(/\n/g, '')
|
||||
.replace(/<!--.*?-->/g, ''),
|
||||
).to.eql(compwrap(expected))
|
||||
})
|
||||
|
||||
it('rich contents of a link are handled properly', () => {
|
||||
|
|
@ -480,7 +455,7 @@ describe('RichContent', () => {
|
|||
'<span>',
|
||||
'</span>',
|
||||
'</a>',
|
||||
'</p>'
|
||||
'</p>',
|
||||
].join('')
|
||||
const expected = [
|
||||
'<p>',
|
||||
|
|
@ -494,7 +469,7 @@ describe('RichContent', () => {
|
|||
'<span>',
|
||||
'</span>',
|
||||
'</a>',
|
||||
'</p>'
|
||||
'</p>',
|
||||
].join('')
|
||||
|
||||
const wrapper = shallowMount(RichContent, {
|
||||
|
|
@ -504,8 +479,8 @@ describe('RichContent', () => {
|
|||
handleLinks: true,
|
||||
greentext: true,
|
||||
emoji: [],
|
||||
html
|
||||
}
|
||||
html,
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.html().replace(/\n/g, '')).to.eql(compwrap(expected))
|
||||
|
|
@ -525,7 +500,7 @@ describe('RichContent', () => {
|
|||
makeMention('Lain'),
|
||||
makeMention('Lain'),
|
||||
makeMention('Lain'),
|
||||
' i just landed in l a where are you'
|
||||
' i just landed in l a where are you',
|
||||
)
|
||||
|
||||
const TestComponent = {
|
||||
|
|
@ -537,7 +512,7 @@ describe('RichContent', () => {
|
|||
${new Array(amount).fill(`<div v-html="${onePost}"/>`)}
|
||||
</div>
|
||||
`,
|
||||
props: ['handleLinks', 'attentions', 'vhtml']
|
||||
props: ['handleLinks', 'attentions', 'vhtml'],
|
||||
}
|
||||
|
||||
const ptest = (handleLinks, vhtml) => {
|
||||
|
|
@ -548,8 +523,8 @@ describe('RichContent', () => {
|
|||
props: {
|
||||
attentions,
|
||||
handleLinks,
|
||||
vhtml
|
||||
}
|
||||
vhtml,
|
||||
},
|
||||
})
|
||||
|
||||
const t1 = performance.now()
|
||||
|
|
|
|||
|
|
@ -5,39 +5,39 @@ import backendInteractorService from 'src/services/backend_interactor_service/ba
|
|||
import { getters } from 'src/modules/users.js'
|
||||
|
||||
const mutations = {
|
||||
clearTimeline: () => {}
|
||||
clearTimeline: () => {},
|
||||
}
|
||||
|
||||
const actions = {
|
||||
fetchUser: () => {},
|
||||
fetchUserByScreenName: () => {}
|
||||
fetchUserByScreenName: () => {},
|
||||
}
|
||||
|
||||
const testGetters = {
|
||||
findUser: state => getters.findUser(state.users),
|
||||
findUserByName: state => getters.findUserByName(state.users),
|
||||
relationship: state => getters.relationship(state.users),
|
||||
findUser: (state) => getters.findUser(state.users),
|
||||
findUserByName: (state) => getters.findUserByName(state.users),
|
||||
relationship: (state) => getters.relationship(state.users),
|
||||
mergedConfig: () => ({
|
||||
colors: '',
|
||||
highlight: {},
|
||||
customTheme: {
|
||||
colors: []
|
||||
}
|
||||
})
|
||||
colors: [],
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
const localUser = {
|
||||
id: 100,
|
||||
is_local: true,
|
||||
screen_name: 'testUser',
|
||||
screen_name_ui: 'testUser'
|
||||
screen_name_ui: 'testUser',
|
||||
}
|
||||
|
||||
const extUser = {
|
||||
id: 100,
|
||||
is_local: false,
|
||||
screen_name: 'testUser@test.instance',
|
||||
screen_name_ui: 'testUser@test.instance'
|
||||
screen_name_ui: 'testUser@test.instance',
|
||||
}
|
||||
|
||||
const externalProfileStore = createStore({
|
||||
|
|
@ -47,13 +47,13 @@ const externalProfileStore = createStore({
|
|||
state: {
|
||||
api: {
|
||||
fetchers: {},
|
||||
backendInteractor: backendInteractorService('')
|
||||
backendInteractor: backendInteractorService(''),
|
||||
},
|
||||
interface: {
|
||||
browserSupport: ''
|
||||
browserSupport: '',
|
||||
},
|
||||
instance: {
|
||||
hideUserStats: true
|
||||
hideUserStats: true,
|
||||
},
|
||||
statuses: {
|
||||
timelines: {
|
||||
|
|
@ -71,7 +71,7 @@ const externalProfileStore = createStore({
|
|||
friends: [],
|
||||
viewing: 'statuses',
|
||||
userId: 100,
|
||||
flushMarker: 0
|
||||
flushMarker: 0,
|
||||
},
|
||||
media: {
|
||||
statuses: [],
|
||||
|
|
@ -87,20 +87,20 @@ const externalProfileStore = createStore({
|
|||
friends: [],
|
||||
viewing: 'statuses',
|
||||
userId: 100,
|
||||
flushMarker: 0
|
||||
}
|
||||
}
|
||||
flushMarker: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
users: {
|
||||
currentUser: {
|
||||
credentials: ''
|
||||
credentials: '',
|
||||
},
|
||||
usersObject: { 100: extUser },
|
||||
usersByNameObject: {},
|
||||
users: [extUser],
|
||||
relationships: {}
|
||||
}
|
||||
}
|
||||
relationships: {},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const localProfileStore = createStore({
|
||||
|
|
@ -110,20 +110,20 @@ const localProfileStore = createStore({
|
|||
state: {
|
||||
api: {
|
||||
fetchers: {},
|
||||
backendInteractor: backendInteractorService('')
|
||||
backendInteractor: backendInteractorService(''),
|
||||
},
|
||||
interface: {
|
||||
browserSupport: ''
|
||||
browserSupport: '',
|
||||
},
|
||||
config: {
|
||||
colors: '',
|
||||
highlight: {},
|
||||
customTheme: {
|
||||
colors: []
|
||||
}
|
||||
colors: [],
|
||||
},
|
||||
},
|
||||
instance: {
|
||||
hideUserStats: true
|
||||
hideUserStats: true,
|
||||
},
|
||||
statuses: {
|
||||
timelines: {
|
||||
|
|
@ -141,7 +141,7 @@ const localProfileStore = createStore({
|
|||
friends: [],
|
||||
viewing: 'statuses',
|
||||
userId: 100,
|
||||
flushMarker: 0
|
||||
flushMarker: 0,
|
||||
},
|
||||
media: {
|
||||
statuses: [],
|
||||
|
|
@ -157,20 +157,20 @@ const localProfileStore = createStore({
|
|||
friends: [],
|
||||
viewing: 'statuses',
|
||||
userId: 100,
|
||||
flushMarker: 0
|
||||
}
|
||||
}
|
||||
flushMarker: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
users: {
|
||||
currentUser: {
|
||||
credentials: ''
|
||||
credentials: '',
|
||||
},
|
||||
usersObject: { 100: localUser },
|
||||
usersByNameObject: { testuser: localUser },
|
||||
users: [localUser],
|
||||
relationships: {}
|
||||
}
|
||||
}
|
||||
relationships: {},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// https://github.com/vuejs/test-utils/issues/1382
|
||||
|
|
@ -182,14 +182,16 @@ describe.skip('UserProfile', () => {
|
|||
mocks: {
|
||||
$route: {
|
||||
params: { id: 100 },
|
||||
name: 'external-user-profile'
|
||||
name: 'external-user-profile',
|
||||
},
|
||||
$t: (msg) => msg
|
||||
}
|
||||
}
|
||||
$t: (msg) => msg,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.find('.user-screen-name').text()).to.eql('@testUser@test.instance')
|
||||
expect(wrapper.find('.user-screen-name').text()).to.eql(
|
||||
'@testUser@test.instance',
|
||||
)
|
||||
})
|
||||
|
||||
it('renders local profile', () => {
|
||||
|
|
@ -199,11 +201,11 @@ describe.skip('UserProfile', () => {
|
|||
mocks: {
|
||||
$route: {
|
||||
params: { name: 'testUser' },
|
||||
name: 'user-profile'
|
||||
name: 'user-profile',
|
||||
},
|
||||
$t: (msg) => msg
|
||||
}
|
||||
}
|
||||
$t: (msg) => msg,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(wrapper.find('.user-screen-name').text()).to.eql('@testUser')
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const getMockStorage = () => {
|
|||
let state = {}
|
||||
|
||||
return {
|
||||
getItem: vi.fn(async key => {
|
||||
getItem: vi.fn(async (key) => {
|
||||
console.info('get:', key, state[key])
|
||||
return state[key]
|
||||
}),
|
||||
|
|
@ -19,7 +19,7 @@ const getMockStorage = () => {
|
|||
}),
|
||||
_clear: () => {
|
||||
state = {}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ describe('piniaPersistPlugin', () => {
|
|||
await mockStorage.setItem('pinia-local-test', { a: 3 })
|
||||
|
||||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2 })
|
||||
state: () => ({ a: 1, b: 2 }),
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
|
|
@ -55,7 +55,7 @@ describe('piniaPersistPlugin', () => {
|
|||
|
||||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2, c: { d: 4, e: 5 } }),
|
||||
persist: {}
|
||||
persist: {},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
|
|
@ -68,7 +68,7 @@ describe('piniaPersistPlugin', () => {
|
|||
|
||||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2, c: { d: 4, e: 5 } }),
|
||||
persist: {}
|
||||
persist: {},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
|
|
@ -84,7 +84,7 @@ describe('piniaPersistPlugin', () => {
|
|||
|
||||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2, c: { d: 4, e: 5 } }),
|
||||
persist: {}
|
||||
persist: {},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
|
|
@ -101,18 +101,21 @@ describe('piniaPersistPlugin', () => {
|
|||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2, c: { d: 4, e: 5 } }),
|
||||
persist: {
|
||||
afterLoad (state) {
|
||||
afterLoad(state) {
|
||||
return {
|
||||
...state,
|
||||
a: 5
|
||||
a: 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
await test.$persistLoaded
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({ a: 4, c: { d: 0 } })
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({
|
||||
a: 4,
|
||||
c: { d: 0 },
|
||||
})
|
||||
expect(test.a).to.eql(5)
|
||||
expect(test.b).to.eql(2)
|
||||
expect(test.c.d).to.eql(0)
|
||||
|
|
@ -124,7 +127,7 @@ describe('piniaPersistPlugin', () => {
|
|||
|
||||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2 }),
|
||||
persist: {}
|
||||
persist: {},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
|
|
@ -138,29 +141,35 @@ describe('piniaPersistPlugin', () => {
|
|||
test('it saves everything if paths is unspecified', async () => {
|
||||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2 }),
|
||||
persist: {}
|
||||
persist: {},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
await test.$persistLoaded
|
||||
test.$patch({ a: 3 })
|
||||
await flushPromises()
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({ a: 3, b: 2 })
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({
|
||||
a: 3,
|
||||
b: 2,
|
||||
})
|
||||
})
|
||||
|
||||
test('it saves only specified paths', async () => {
|
||||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2, c: { d: 4, e: 5 } }),
|
||||
persist: {
|
||||
paths: ['a', 'c.d']
|
||||
}
|
||||
paths: ['a', 'c.d'],
|
||||
},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
await test.$persistLoaded
|
||||
test.$patch({ a: 3 })
|
||||
await flushPromises()
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({ a: 3, c: { d: 4 } })
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({
|
||||
a: 3,
|
||||
c: { d: 4 },
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -171,8 +180,8 @@ describe('piniaPersistPlugin', () => {
|
|||
state: () => ({ a: 1, b: 2 }),
|
||||
persist: {
|
||||
onSaveSuccess,
|
||||
onSaveError
|
||||
}
|
||||
onSaveError,
|
||||
},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
|
|
@ -194,26 +203,35 @@ describe('piniaPersistPlugin', () => {
|
|||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2 }),
|
||||
actions: {
|
||||
increaseA () {
|
||||
increaseA() {
|
||||
++this.a
|
||||
},
|
||||
increaseB () {
|
||||
increaseB() {
|
||||
++this.b
|
||||
}
|
||||
},
|
||||
},
|
||||
persist: {
|
||||
saveImmediatelyActions: ['increaseA']
|
||||
}
|
||||
saveImmediatelyActions: ['increaseA'],
|
||||
},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
await test.$persistLoaded
|
||||
await test.increaseA()
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({ a: 2, b: 2 })
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({
|
||||
a: 2,
|
||||
b: 2,
|
||||
})
|
||||
await test.increaseB()
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({ a: 2, b: 2 })
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({
|
||||
a: 2,
|
||||
b: 2,
|
||||
})
|
||||
await test.increaseA()
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({ a: 3, b: 3 })
|
||||
expect(await mockStorage.getItem('pinia-local-test')).to.eql({
|
||||
a: 3,
|
||||
b: 3,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -225,8 +243,8 @@ describe('piniaPersistPlugin', () => {
|
|||
state: () => ({ a: 1, b: 2 }),
|
||||
persist: {
|
||||
onSaveSuccess,
|
||||
onSaveError
|
||||
}
|
||||
onSaveError,
|
||||
},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
|
|
@ -251,8 +269,8 @@ describe('piniaPersistPlugin', () => {
|
|||
state: () => ({ a: 1, b: 2 }),
|
||||
persist: {
|
||||
onSaveSuccess,
|
||||
onSaveError
|
||||
}
|
||||
onSaveError,
|
||||
},
|
||||
})
|
||||
|
||||
const test = useTestStore()
|
||||
|
|
@ -269,15 +287,15 @@ describe('piniaPersistPlugin', () => {
|
|||
describe('afterLoad', () => {
|
||||
test('it is called with the saved state object', async () => {
|
||||
await mockStorage.setItem('pinia-local-test', { a: 2 })
|
||||
const afterLoad = vi.fn(async orig => {
|
||||
const afterLoad = vi.fn(async (orig) => {
|
||||
return { a: orig.a + 1 }
|
||||
})
|
||||
|
||||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2 }),
|
||||
persist: {
|
||||
afterLoad
|
||||
}
|
||||
afterLoad,
|
||||
},
|
||||
})
|
||||
const test = useTestStore()
|
||||
await test.$persistLoaded
|
||||
|
|
@ -294,8 +312,8 @@ describe('piniaPersistPlugin', () => {
|
|||
const useTestStore = defineStore('test', {
|
||||
state: () => ({ a: 1, b: 2 }),
|
||||
persist: {
|
||||
afterLoad
|
||||
}
|
||||
afterLoad,
|
||||
},
|
||||
})
|
||||
const test = useTestStore()
|
||||
await test.$persistLoaded
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ describe('The serverSideStorage module', () => {
|
|||
describe('setServerSideStorage', () => {
|
||||
const user = {
|
||||
created_at: new Date('1999-02-09'),
|
||||
storage: {}
|
||||
storage: {},
|
||||
}
|
||||
|
||||
it('should initialize storage if none present', () => {
|
||||
|
|
@ -51,29 +51,27 @@ describe('The serverSideStorage module', () => {
|
|||
store.cache = {
|
||||
_timestamp: Date.now(),
|
||||
_version: VERSION,
|
||||
...cloneDeep(defaultState)
|
||||
...cloneDeep(defaultState),
|
||||
}
|
||||
|
||||
store.setServerSideStorage(
|
||||
{
|
||||
...user,
|
||||
storage: {
|
||||
_timestamp: 123,
|
||||
_version: VERSION,
|
||||
flagStorage: {
|
||||
...defaultState.flagStorage,
|
||||
updateCounter: 1
|
||||
},
|
||||
prefsStorage: {
|
||||
...defaultState.prefsStorage
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
store.setServerSideStorage({
|
||||
...user,
|
||||
storage: {
|
||||
_timestamp: 123,
|
||||
_version: VERSION,
|
||||
flagStorage: {
|
||||
...defaultState.flagStorage,
|
||||
updateCounter: 1,
|
||||
},
|
||||
prefsStorage: {
|
||||
...defaultState.prefsStorage,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
expect(store.cache.flagStorage).to.eql({
|
||||
...defaultState.flagStorage,
|
||||
updateCounter: 1
|
||||
updateCounter: 1,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -81,19 +79,17 @@ describe('The serverSideStorage module', () => {
|
|||
const store = useServerSideStorageStore()
|
||||
store.cache = null
|
||||
|
||||
store.setServerSideStorage(
|
||||
{
|
||||
...user,
|
||||
storage: {
|
||||
_timestamp: 123,
|
||||
_version: VERSION,
|
||||
flagStorage: {
|
||||
...defaultState.flagStorage,
|
||||
updateCounter: 999
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
store.setServerSideStorage({
|
||||
...user,
|
||||
storage: {
|
||||
_timestamp: 123,
|
||||
_version: VERSION,
|
||||
flagStorage: {
|
||||
...defaultState.flagStorage,
|
||||
updateCounter: 999,
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(store.cache._timestamp).to.eql(123)
|
||||
expect(store.flagStorage.updateCounter).to.eql(999)
|
||||
expect(store.cache.flagStorage.updateCounter).to.eql(999)
|
||||
|
|
@ -118,7 +114,7 @@ describe('The serverSideStorage module', () => {
|
|||
operation: 'set',
|
||||
args: [1],
|
||||
// should have A timestamp, we don't really care what it is
|
||||
timestamp: store.prefsStorage._journal[0].timestamp
|
||||
timestamp: store.prefsStorage._journal[0].timestamp,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -127,7 +123,10 @@ describe('The serverSideStorage module', () => {
|
|||
store.setPreference({ path: 'simple.testing', value: 1 })
|
||||
store.setPreference({ path: 'simple.testing', value: 2 })
|
||||
store.addCollectionPreference({ path: 'collections.testing', value: 2 })
|
||||
store.removeCollectionPreference({ path: 'collections.testing', value: 2 })
|
||||
store.removeCollectionPreference({
|
||||
path: 'collections.testing',
|
||||
value: 2,
|
||||
})
|
||||
store.updateCache({ username: 'test' })
|
||||
expect(store.prefsStorage.simple.testing).to.eql(2)
|
||||
expect(store.prefsStorage.collections.testing).to.eql([])
|
||||
|
|
@ -137,14 +136,14 @@ describe('The serverSideStorage module', () => {
|
|||
operation: 'set',
|
||||
args: [2],
|
||||
// should have A timestamp, we don't really care what it is
|
||||
timestamp: store.prefsStorage._journal[0].timestamp
|
||||
timestamp: store.prefsStorage._journal[0].timestamp,
|
||||
})
|
||||
expect(store.prefsStorage._journal[1]).to.eql({
|
||||
path: 'collections.testing',
|
||||
operation: 'removeFromCollection',
|
||||
args: [2],
|
||||
// should have A timestamp, we don't really care what it is
|
||||
timestamp: store.prefsStorage._journal[1].timestamp
|
||||
timestamp: store.prefsStorage._journal[1].timestamp,
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -173,16 +172,26 @@ describe('The serverSideStorage module', () => {
|
|||
const store = useServerSideStorageStore()
|
||||
store.setPreference({ path: 'simple.object.foo', value: 1 })
|
||||
expect(() => store.unsetPreference({ path: 'simple' })).to.throw()
|
||||
expect(() => store.unsetPreference({ path: 'simple.object' })).to.throw()
|
||||
expect(() =>
|
||||
store.unsetPreference({ path: 'simple.object' }),
|
||||
).to.throw()
|
||||
})
|
||||
|
||||
it('should not allow (un)setting depth > 3', () => {
|
||||
const store = useServerSideStorageStore()
|
||||
store.setPreference({ path: 'simple.object', value: {} })
|
||||
expect(() => store.setPreference({ path: 'simple.object.lv3', value: 1 })).to.not.throw()
|
||||
expect(() => store.setPreference({ path: 'simple.object.lv3.lv4', value: 1})).to.throw()
|
||||
expect(() => store.unsetPreference({ path: 'simple.object.lv3', value: 1 })).to.not.throw()
|
||||
expect(() => store.unsetPreference({ path: 'simple.object.lv3.lv4', value: 1})).to.throw()
|
||||
expect(() =>
|
||||
store.setPreference({ path: 'simple.object.lv3', value: 1 }),
|
||||
).to.not.throw()
|
||||
expect(() =>
|
||||
store.setPreference({ path: 'simple.object.lv3.lv4', value: 1 }),
|
||||
).to.throw()
|
||||
expect(() =>
|
||||
store.unsetPreference({ path: 'simple.object.lv3', value: 1 }),
|
||||
).to.not.throw()
|
||||
expect(() =>
|
||||
store.unsetPreference({ path: 'simple.object.lv3.lv4', value: 1 }),
|
||||
).to.throw()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -200,33 +209,65 @@ describe('The serverSideStorage module', () => {
|
|||
})
|
||||
describe('_getRecentData', () => {
|
||||
it('should handle nulls correctly', () => {
|
||||
expect(_getRecentData(null, null, true)).to.eql({ recent: null, stale: null, needUpload: true })
|
||||
expect(_getRecentData(null, null, true)).to.eql({
|
||||
recent: null,
|
||||
stale: null,
|
||||
needUpload: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('doesn\'t choke on invalid data', () => {
|
||||
expect(_getRecentData({ a: 1 }, { b: 2 }, true)).to.eql({ recent: null, stale: null, needUpload: true })
|
||||
it("doesn't choke on invalid data", () => {
|
||||
expect(_getRecentData({ a: 1 }, { b: 2 }, true)).to.eql({
|
||||
recent: null,
|
||||
stale: null,
|
||||
needUpload: true,
|
||||
})
|
||||
})
|
||||
|
||||
it('should prefer the valid non-null correctly, needUpload works properly', () => {
|
||||
const nonNull = { _version: VERSION, _timestamp: 1 }
|
||||
expect(_getRecentData(nonNull, null, true)).to.eql({ recent: nonNull, stale: null, needUpload: true })
|
||||
expect(_getRecentData(null, nonNull, true)).to.eql({ recent: nonNull, stale: null, needUpload: false })
|
||||
expect(_getRecentData(nonNull, null, true)).to.eql({
|
||||
recent: nonNull,
|
||||
stale: null,
|
||||
needUpload: true,
|
||||
})
|
||||
expect(_getRecentData(null, nonNull, true)).to.eql({
|
||||
recent: nonNull,
|
||||
stale: null,
|
||||
needUpload: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('should prefer the one with higher timestamp', () => {
|
||||
const a = { _version: VERSION, _timestamp: 1 }
|
||||
const b = { _version: VERSION, _timestamp: 2 }
|
||||
|
||||
expect(_getRecentData(a, b, true)).to.eql({ recent: b, stale: a, needUpload: false })
|
||||
expect(_getRecentData(b, a, true)).to.eql({ recent: b, stale: a, needUpload: false })
|
||||
expect(_getRecentData(a, b, true)).to.eql({
|
||||
recent: b,
|
||||
stale: a,
|
||||
needUpload: false,
|
||||
})
|
||||
expect(_getRecentData(b, a, true)).to.eql({
|
||||
recent: b,
|
||||
stale: a,
|
||||
needUpload: false,
|
||||
})
|
||||
})
|
||||
|
||||
it('case where both are same', () => {
|
||||
const a = { _version: VERSION, _timestamp: 3 }
|
||||
const b = { _version: VERSION, _timestamp: 3 }
|
||||
|
||||
expect(_getRecentData(a, b, true)).to.eql({ recent: b, stale: a, needUpload: false })
|
||||
expect(_getRecentData(b, a, true)).to.eql({ recent: b, stale: a, needUpload: false })
|
||||
expect(_getRecentData(a, b, true)).to.eql({
|
||||
recent: b,
|
||||
stale: a,
|
||||
needUpload: false,
|
||||
})
|
||||
expect(_getRecentData(b, a, true)).to.eql({
|
||||
recent: b,
|
||||
stale: a,
|
||||
needUpload: false,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -235,10 +276,17 @@ describe('The serverSideStorage module', () => {
|
|||
expect(_getAllFlags(null, null)).to.eql([])
|
||||
})
|
||||
it('should output list of keys if passed single object', () => {
|
||||
expect(_getAllFlags({ flagStorage: { a: 1, b: 1, c: 1 } }, null)).to.eql(['a', 'b', 'c'])
|
||||
expect(
|
||||
_getAllFlags({ flagStorage: { a: 1, b: 1, c: 1 } }, null),
|
||||
).to.eql(['a', 'b', 'c'])
|
||||
})
|
||||
it('should union keys of both objects', () => {
|
||||
expect(_getAllFlags({ flagStorage: { a: 1, b: 1, c: 1 } }, { flagStorage: { c: 1, d: 1 } })).to.eql(['a', 'b', 'c', 'd'])
|
||||
expect(
|
||||
_getAllFlags(
|
||||
{ flagStorage: { a: 1, b: 1, c: 1 } },
|
||||
{ flagStorage: { c: 1, d: 1 } },
|
||||
),
|
||||
).to.eql(['a', 'b', 'c', 'd'])
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -248,7 +296,8 @@ describe('The serverSideStorage module', () => {
|
|||
_mergeFlags(
|
||||
{ flagStorage: { a: 0, b: 3 } },
|
||||
{ flagStorage: { b: 1, c: 4, d: 9 } },
|
||||
['a', 'b', 'c', 'd'])
|
||||
['a', 'b', 'c', 'd'],
|
||||
),
|
||||
).to.eql({ a: 0, b: 3, c: 4, d: 9 })
|
||||
})
|
||||
})
|
||||
|
|
@ -262,25 +311,30 @@ describe('The serverSideStorage module', () => {
|
|||
simple: { a: 1, b: 0, c: true },
|
||||
_journal: [
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 2 },
|
||||
{ path: 'simple.c', operation: 'set', args: [true], timestamp: 4 }
|
||||
]
|
||||
{
|
||||
path: 'simple.c',
|
||||
operation: 'set',
|
||||
args: [true],
|
||||
timestamp: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
// STALE
|
||||
{
|
||||
simple: { a: 1, b: 1, c: false },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: [1], timestamp: 1 },
|
||||
{ path: 'simple.b', operation: 'set', args: [1], timestamp: 3 }
|
||||
]
|
||||
}
|
||||
)
|
||||
{ path: 'simple.b', operation: 'set', args: [1], timestamp: 3 },
|
||||
],
|
||||
},
|
||||
),
|
||||
).to.eql({
|
||||
simple: { a: 1, b: 1, c: true },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: [1], timestamp: 1 },
|
||||
{ path: 'simple.b', operation: 'set', args: [1], timestamp: 3 },
|
||||
{ path: 'simple.c', operation: 'set', args: [true], timestamp: 4 }
|
||||
]
|
||||
{ path: 'simple.c', operation: 'set', args: [true], timestamp: 4 },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -292,25 +346,30 @@ describe('The serverSideStorage module', () => {
|
|||
simple: { a: 1, b: 0, c: false },
|
||||
_journal: [
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 2 },
|
||||
{ path: 'simple.c', operation: 'set', args: [false], timestamp: 4 }
|
||||
]
|
||||
{
|
||||
path: 'simple.c',
|
||||
operation: 'set',
|
||||
args: [false],
|
||||
timestamp: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
// STALE
|
||||
{
|
||||
simple: { a: 0, b: 0, c: true },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: [0], timestamp: 1 },
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 3 }
|
||||
]
|
||||
}
|
||||
)
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 3 },
|
||||
],
|
||||
},
|
||||
),
|
||||
).to.eql({
|
||||
simple: { a: 0, b: 0, c: false },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: [0], timestamp: 1 },
|
||||
{ path: 'simple.b', operation: 'set', args: [0], timestamp: 3 },
|
||||
{ path: 'simple.c', operation: 'set', args: [false], timestamp: 4 }
|
||||
]
|
||||
{ path: 'simple.c', operation: 'set', args: [false], timestamp: 4 },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -321,22 +380,32 @@ describe('The serverSideStorage module', () => {
|
|||
{
|
||||
simple: { a: 'foo' },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: ['foo'], timestamp: 2 }
|
||||
]
|
||||
{
|
||||
path: 'simple.a',
|
||||
operation: 'set',
|
||||
args: ['foo'],
|
||||
timestamp: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
// STALE
|
||||
{
|
||||
simple: { a: 'bar' },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: ['bar'], timestamp: 4 }
|
||||
]
|
||||
}
|
||||
)
|
||||
{
|
||||
path: 'simple.a',
|
||||
operation: 'set',
|
||||
args: ['bar'],
|
||||
timestamp: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
).to.eql({
|
||||
simple: { a: 'bar' },
|
||||
_journal: [
|
||||
{ path: 'simple.a', operation: 'set', args: ['bar'], timestamp: 4 }
|
||||
]
|
||||
{ path: 'simple.a', operation: 'set', args: ['bar'], timestamp: 4 },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -347,22 +416,37 @@ describe('The serverSideStorage module', () => {
|
|||
{
|
||||
simple: { lv2: { lv3: 'foo' } },
|
||||
_journal: [
|
||||
{ path: 'simple.lv2.lv3', operation: 'set', args: ['foo'], timestamp: 2 }
|
||||
]
|
||||
{
|
||||
path: 'simple.lv2.lv3',
|
||||
operation: 'set',
|
||||
args: ['foo'],
|
||||
timestamp: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
// STALE
|
||||
{
|
||||
simple: { lv2: { lv3: 'bar' } },
|
||||
_journal: [
|
||||
{ path: 'simple.lv2.lv3', operation: 'set', args: ['bar'], timestamp: 4 }
|
||||
]
|
||||
}
|
||||
)
|
||||
{
|
||||
path: 'simple.lv2.lv3',
|
||||
operation: 'set',
|
||||
args: ['bar'],
|
||||
timestamp: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
).to.eql({
|
||||
simple: { lv2: { lv3: 'bar' } },
|
||||
_journal: [
|
||||
{ path: 'simple.lv2.lv3', operation: 'set', args: ['bar'], timestamp: 4 }
|
||||
]
|
||||
{
|
||||
path: 'simple.lv2.lv3',
|
||||
operation: 'set',
|
||||
args: ['bar'],
|
||||
timestamp: 4,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -373,22 +457,37 @@ describe('The serverSideStorage module', () => {
|
|||
{
|
||||
simple: { lv2: { lv3: 'foo' } },
|
||||
_journal: [
|
||||
{ path: 'simple.lv2.lv3', operation: 'set', args: ['foo'], timestamp: 2 }
|
||||
]
|
||||
{
|
||||
path: 'simple.lv2.lv3',
|
||||
operation: 'set',
|
||||
args: ['foo'],
|
||||
timestamp: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
// STALE
|
||||
{
|
||||
simple: { lv2: {} },
|
||||
_journal: [
|
||||
{ path: 'simple.lv2.lv3', operation: 'unset', args: [], timestamp: 4 }
|
||||
]
|
||||
}
|
||||
)
|
||||
{
|
||||
path: 'simple.lv2.lv3',
|
||||
operation: 'unset',
|
||||
args: [],
|
||||
timestamp: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
),
|
||||
).to.eql({
|
||||
simple: { lv2: {} },
|
||||
_journal: [
|
||||
{ path: 'simple.lv2.lv3', operation: 'unset', args: [], timestamp: 4 }
|
||||
]
|
||||
{
|
||||
path: 'simple.lv2.lv3',
|
||||
operation: 'unset',
|
||||
args: [],
|
||||
timestamp: 4,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -402,12 +501,25 @@ describe('The serverSideStorage module', () => {
|
|||
it('should trim all flags to known when reset is set to 1000', () => {
|
||||
const totalFlags = { a: 0, b: 3, c: 33, reset: COMMAND_TRIM_FLAGS }
|
||||
|
||||
expect(_resetFlags(totalFlags, { a: 0, b: 0, reset: 0 })).to.eql({ a: 0, b: 3, reset: 0 })
|
||||
expect(_resetFlags(totalFlags, { a: 0, b: 0, reset: 0 })).to.eql({
|
||||
a: 0,
|
||||
b: 3,
|
||||
reset: 0,
|
||||
})
|
||||
})
|
||||
it('should trim all flags to known and reset when reset is set to 1001', () => {
|
||||
const totalFlags = { a: 0, b: 3, c: 33, reset: COMMAND_TRIM_FLAGS_AND_RESET }
|
||||
const totalFlags = {
|
||||
a: 0,
|
||||
b: 3,
|
||||
c: 33,
|
||||
reset: COMMAND_TRIM_FLAGS_AND_RESET,
|
||||
}
|
||||
|
||||
expect(_resetFlags(totalFlags, { a: 0, b: 0, reset: 0 })).to.eql({ a: 0, b: 0, reset: 0 })
|
||||
expect(_resetFlags(totalFlags, { a: 0, b: 0, reset: 0 })).to.eql({
|
||||
a: 0,
|
||||
b: 0,
|
||||
reset: 0,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import { defaultState, mutations, prepareStatus } from '../../../../src/modules/statuses.js'
|
||||
import {
|
||||
defaultState,
|
||||
mutations,
|
||||
prepareStatus,
|
||||
} from '../../../../src/modules/statuses.js'
|
||||
|
||||
|
||||
const makeMockStatus = ({ id, text, type = 'status' }) => {
|
||||
return {
|
||||
id,
|
||||
|
|
@ -10,7 +13,7 @@ const makeMockStatus = ({ id, text, type = 'status' }) => {
|
|||
fave_num: 0,
|
||||
uri: '',
|
||||
type,
|
||||
attentions: []
|
||||
attentions: [],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -27,7 +30,10 @@ describe('Statuses module', () => {
|
|||
const state = defaultState()
|
||||
const status = makeMockStatus({ id: '1' })
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
timeline: 'public',
|
||||
})
|
||||
|
||||
expect(state.allStatuses).to.eql([status])
|
||||
expect(state.timelines.public.statuses).to.eql([status])
|
||||
|
|
@ -39,8 +45,14 @@ describe('Statuses module', () => {
|
|||
const state = defaultState()
|
||||
const status = makeMockStatus({ id: '1' })
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' })
|
||||
mutations.addNewStatuses(state, { statuses: [status], timeline: 'friends' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
timeline: 'public',
|
||||
})
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
timeline: 'friends',
|
||||
})
|
||||
|
||||
expect(state.allStatuses).to.eql([status])
|
||||
expect(state.timelines.public.statuses).to.eql([status])
|
||||
|
|
@ -69,7 +81,11 @@ describe('Statuses module', () => {
|
|||
const state = defaultState()
|
||||
const status = makeMockStatus({ id: '1' })
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
|
||||
expect(state.allStatuses).to.eql([status])
|
||||
expect(state.timelines.public.statuses).to.eql([status])
|
||||
|
|
@ -82,12 +98,24 @@ describe('Statuses module', () => {
|
|||
const status = makeMockStatus({ id: '1' })
|
||||
const secondStatus = makeMockStatus({ id: '2' })
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
expect(state.timelines.public.maxId).to.eql('1')
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [secondStatus], showImmediately: true, timeline: 'public', noIdUpdate: true })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [secondStatus],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
noIdUpdate: true,
|
||||
})
|
||||
expect(state.timelines.public.statuses).to.eql([secondStatus, status])
|
||||
expect(state.timelines.public.visibleStatuses).to.eql([secondStatus, status])
|
||||
expect(state.timelines.public.visibleStatuses).to.eql([
|
||||
secondStatus,
|
||||
status,
|
||||
])
|
||||
expect(state.timelines.public.maxId).to.eql('1')
|
||||
})
|
||||
|
||||
|
|
@ -98,17 +126,42 @@ describe('Statuses module', () => {
|
|||
const statusTwo = makeMockStatus({ id: '2' })
|
||||
const statusThree = makeMockStatus({ id: '4' })
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [nonVisibleStatus], showImmediately: false, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [nonVisibleStatus],
|
||||
showImmediately: false,
|
||||
timeline: 'public',
|
||||
})
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, { statuses: [statusTwo], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [statusTwo],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
|
||||
expect(state.timelines.public.minVisibleId).to.equal('2')
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [statusThree], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [statusThree],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
|
||||
expect(state.timelines.public.statuses).to.eql([statusThree, status, statusTwo, nonVisibleStatus])
|
||||
expect(state.timelines.public.visibleStatuses).to.eql([statusThree, status, statusTwo])
|
||||
expect(state.timelines.public.statuses).to.eql([
|
||||
statusThree,
|
||||
status,
|
||||
statusTwo,
|
||||
nonVisibleStatus,
|
||||
])
|
||||
expect(state.timelines.public.visibleStatuses).to.eql([
|
||||
statusThree,
|
||||
status,
|
||||
statusTwo,
|
||||
])
|
||||
})
|
||||
|
||||
it('splits retweets from their status and links them', () => {
|
||||
|
|
@ -120,7 +173,11 @@ describe('Statuses module', () => {
|
|||
retweet.retweeted_status = status
|
||||
|
||||
// It adds both statuses, but only the retweet to visible.
|
||||
mutations.addNewStatuses(state, { statuses: [retweet], timeline: 'public', showImmediately: true })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [retweet],
|
||||
timeline: 'public',
|
||||
showImmediately: true,
|
||||
})
|
||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
||||
expect(state.timelines.public.statuses).to.have.length(1)
|
||||
expect(state.allStatuses).to.have.length(2)
|
||||
|
|
@ -128,7 +185,10 @@ describe('Statuses module', () => {
|
|||
expect(state.allStatuses[1].id).to.equal('2')
|
||||
|
||||
// It refers to the modified status.
|
||||
mutations.addNewStatuses(state, { statuses: [modStatus], timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [modStatus],
|
||||
timeline: 'public',
|
||||
})
|
||||
expect(state.allStatuses).to.have.length(2)
|
||||
expect(state.allStatuses[0].id).to.equal('1')
|
||||
expect(state.allStatuses[0].text).to.equal(modStatus.text)
|
||||
|
|
@ -142,12 +202,20 @@ describe('Statuses module', () => {
|
|||
const modStatus = makeMockStatus({ id: '1', text: 'something else' })
|
||||
|
||||
// Add original status
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
||||
expect(state.allStatuses).to.have.length(1)
|
||||
|
||||
// Add new version of status
|
||||
mutations.addNewStatuses(state, { statuses: [modStatus], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [modStatus],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
||||
expect(state.allStatuses).to.have.length(1)
|
||||
expect(state.allStatuses[0].text).to.eql(modStatus.text)
|
||||
|
|
@ -161,12 +229,20 @@ describe('Statuses module', () => {
|
|||
retweet.retweeted_status = modStatus
|
||||
|
||||
// Add original status
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
||||
expect(state.allStatuses).to.have.length(1)
|
||||
|
||||
// Add new version of status
|
||||
mutations.addNewStatuses(state, { statuses: [retweet], showImmediately: false, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [retweet],
|
||||
showImmediately: false,
|
||||
timeline: 'public',
|
||||
})
|
||||
expect(state.timelines.public.visibleStatuses).to.have.length(1)
|
||||
// Don't add the retweet itself if the tweet is visible
|
||||
expect(state.timelines.public.statuses).to.have.length(1)
|
||||
|
|
@ -184,18 +260,30 @@ describe('Statuses module', () => {
|
|||
in_reply_to_status_id: '1', // The API uses strings here...
|
||||
uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00',
|
||||
text: 'a favorited something by b',
|
||||
user: { id: '99' }
|
||||
user: { id: '99' },
|
||||
}
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, { statuses: [favorite], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [favorite],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
|
||||
expect(state.timelines.public.visibleStatuses.length).to.eql(1)
|
||||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1)
|
||||
expect(state.timelines.public.maxId).to.eq(favorite.id)
|
||||
|
||||
// Adding it again does nothing
|
||||
mutations.addNewStatuses(state, { statuses: [favorite], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [favorite],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
|
||||
expect(state.timelines.public.visibleStatuses.length).to.eql(1)
|
||||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1)
|
||||
|
|
@ -203,7 +291,7 @@ describe('Statuses module', () => {
|
|||
|
||||
// If something is favorited by the current user, it also sets the 'favorited' property but does not increment counter to avoid over-counting. Counter is incremented (updated, really) via response to the favorite request.
|
||||
const user = {
|
||||
id: '1'
|
||||
id: '1',
|
||||
}
|
||||
|
||||
const ownFavorite = {
|
||||
|
|
@ -212,10 +300,15 @@ describe('Statuses module', () => {
|
|||
in_reply_to_status_id: '1', // The API uses strings here...
|
||||
uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00',
|
||||
text: 'a favorited something by b',
|
||||
user
|
||||
user,
|
||||
}
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [ownFavorite], showImmediately: true, timeline: 'public', user })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [ownFavorite],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
user,
|
||||
})
|
||||
|
||||
expect(state.timelines.public.visibleStatuses.length).to.eql(1)
|
||||
expect(state.timelines.public.visibleStatuses[0].fave_num).to.eql(1)
|
||||
|
|
@ -229,11 +322,21 @@ describe('Statuses module', () => {
|
|||
const status = makeMockStatus({ id: '1' })
|
||||
status.emoji_reactions = [{ name: '😂', count: 1, accounts: [] }]
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addOwnReaction(state, { id: '1', emoji: '😂', currentUser: { id: 'me' } })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
mutations.addOwnReaction(state, {
|
||||
id: '1',
|
||||
emoji: '😂',
|
||||
currentUser: { id: 'me' },
|
||||
})
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(2)
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].me).to.eql(true)
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].accounts[0].id).to.eql('me')
|
||||
expect(
|
||||
state.allStatusesObject['1'].emoji_reactions[0].accounts[0].id,
|
||||
).to.eql('me')
|
||||
})
|
||||
|
||||
it('adds a new reaction', () => {
|
||||
|
|
@ -241,32 +344,64 @@ describe('Statuses module', () => {
|
|||
const status = makeMockStatus({ id: '1' })
|
||||
status.emoji_reactions = []
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addOwnReaction(state, { id: '1', emoji: '😂', currentUser: { id: 'me' } })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
mutations.addOwnReaction(state, {
|
||||
id: '1',
|
||||
emoji: '😂',
|
||||
currentUser: { id: 'me' },
|
||||
})
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(1)
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].me).to.eql(true)
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].accounts[0].id).to.eql('me')
|
||||
expect(
|
||||
state.allStatusesObject['1'].emoji_reactions[0].accounts[0].id,
|
||||
).to.eql('me')
|
||||
})
|
||||
|
||||
it('decreases count in existing reaction', () => {
|
||||
const state = defaultState()
|
||||
const status = makeMockStatus({ id: '1' })
|
||||
status.emoji_reactions = [{ name: '😂', count: 2, accounts: [{ id: 'me' }] }]
|
||||
status.emoji_reactions = [
|
||||
{ name: '😂', count: 2, accounts: [{ id: 'me' }] },
|
||||
]
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.removeOwnReaction(state, { id: '1', emoji: '😂', currentUser: { id: 'me' } })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
mutations.removeOwnReaction(state, {
|
||||
id: '1',
|
||||
emoji: '😂',
|
||||
currentUser: { id: 'me' },
|
||||
})
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].count).to.eql(1)
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].me).to.eql(false)
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].accounts).to.eql([])
|
||||
expect(state.allStatusesObject['1'].emoji_reactions[0].accounts).to.eql(
|
||||
[],
|
||||
)
|
||||
})
|
||||
|
||||
it('removes a reaction', () => {
|
||||
const state = defaultState()
|
||||
const status = makeMockStatus({ id: '1' })
|
||||
status.emoji_reactions = [{ name: '😂', count: 1, accounts: [{ id: 'me' }] }]
|
||||
status.emoji_reactions = [
|
||||
{ name: '😂', count: 1, accounts: [{ id: 'me' }] },
|
||||
]
|
||||
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.removeOwnReaction(state, { id: '1', emoji: '😂', currentUser: { id: 'me' } })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
mutations.removeOwnReaction(state, {
|
||||
id: '1',
|
||||
emoji: '😂',
|
||||
currentUser: { id: 'me' },
|
||||
})
|
||||
expect(state.allStatusesObject['1'].emoji_reactions.length).to.eql(0)
|
||||
})
|
||||
})
|
||||
|
|
@ -275,9 +410,17 @@ describe('Statuses module', () => {
|
|||
it('resets the minId to the min of the visible statuses when adding new to visible statuses', () => {
|
||||
const state = defaultState()
|
||||
const status = makeMockStatus({ id: '10' })
|
||||
mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [status],
|
||||
showImmediately: true,
|
||||
timeline: 'public',
|
||||
})
|
||||
const newStatus = makeMockStatus({ id: '20' })
|
||||
mutations.addNewStatuses(state, { statuses: [newStatus], showImmediately: false, timeline: 'public' })
|
||||
mutations.addNewStatuses(state, {
|
||||
statuses: [newStatus],
|
||||
showImmediately: false,
|
||||
timeline: 'public',
|
||||
})
|
||||
state.timelines.public.minId = '5'
|
||||
mutations.showNewStatuses(state, { timeline: 'public' })
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import { cloneDeep } from 'lodash'
|
||||
|
||||
import { defaultState, mutations, getters } from '../../../../src/modules/users.js'
|
||||
import {
|
||||
defaultState,
|
||||
mutations,
|
||||
getters,
|
||||
} from '../../../../src/modules/users.js'
|
||||
|
||||
describe('The users module', () => {
|
||||
describe('mutations', () => {
|
||||
|
|
@ -23,22 +27,18 @@ describe('The users module', () => {
|
|||
const state = cloneDeep(defaultState)
|
||||
const user = {
|
||||
id: '1',
|
||||
fields: [
|
||||
{ name: 'Label 1', value: 'Content 1' }
|
||||
]
|
||||
fields: [{ name: 'Label 1', value: 'Content 1' }],
|
||||
}
|
||||
const firstModUser = {
|
||||
id: '1',
|
||||
fields: [
|
||||
{ name: 'Label 2', value: 'Content 2' },
|
||||
{ name: 'Label 3', value: 'Content 3' }
|
||||
]
|
||||
{ name: 'Label 3', value: 'Content 3' },
|
||||
],
|
||||
}
|
||||
const secondModUser = {
|
||||
id: '1',
|
||||
fields: [
|
||||
{ name: 'Label 4', value: 'Content 4' }
|
||||
]
|
||||
fields: [{ name: 'Label 4', value: 'Content 4' }],
|
||||
}
|
||||
|
||||
mutations.addNewUsers(state, [user])
|
||||
|
|
@ -61,11 +61,11 @@ describe('The users module', () => {
|
|||
const user = { screen_name: 'Guy', id: '1' }
|
||||
const state = {
|
||||
usersObject: {
|
||||
1: user
|
||||
1: user,
|
||||
},
|
||||
usersByNameObject: {
|
||||
guy: user
|
||||
}
|
||||
guy: user,
|
||||
},
|
||||
}
|
||||
const name = 'Guy'
|
||||
expect(getters.findUser(state)(name)).to.eql(undefined)
|
||||
|
|
@ -75,11 +75,11 @@ describe('The users module', () => {
|
|||
const user = { screen_name: 'Guy', id: '1' }
|
||||
const state = {
|
||||
usersObject: {
|
||||
1: user
|
||||
1: user,
|
||||
},
|
||||
usersByNameObject: {
|
||||
guy: user
|
||||
}
|
||||
guy: user,
|
||||
},
|
||||
}
|
||||
const id = '1'
|
||||
const expected = { screen_name: 'Guy', id: '1' }
|
||||
|
|
@ -92,11 +92,11 @@ describe('The users module', () => {
|
|||
const user = { screen_name: 'Guy', id: '1' }
|
||||
const state = {
|
||||
usersObject: {
|
||||
1: user
|
||||
1: user,
|
||||
},
|
||||
usersByNameObject: {
|
||||
guy: user
|
||||
}
|
||||
guy: user,
|
||||
},
|
||||
}
|
||||
const name = 'Guy'
|
||||
const expected = { screen_name: 'Guy', id: '1' }
|
||||
|
|
@ -107,11 +107,11 @@ describe('The users module', () => {
|
|||
const user = { screen_name: 'Guy', id: '1' }
|
||||
const state = {
|
||||
usersObject: {
|
||||
1: user
|
||||
1: user,
|
||||
},
|
||||
usersByNameObject: {
|
||||
guy: user
|
||||
}
|
||||
guy: user,
|
||||
},
|
||||
}
|
||||
const id = '1'
|
||||
expect(getters.findUserByName(state)(id)).to.eql(undefined)
|
||||
|
|
|
|||
|
|
@ -3,21 +3,21 @@ import chatService from '../../../../../src/services/chat_service/chat_service.j
|
|||
const message1 = {
|
||||
id: '9wLkdcmQXD21Oy8lEX',
|
||||
idempotency_key: '1',
|
||||
created_at: (new Date('2020-06-22T18:45:53.000Z'))
|
||||
created_at: new Date('2020-06-22T18:45:53.000Z'),
|
||||
}
|
||||
|
||||
const message2 = {
|
||||
id: '9wLkdp6ihaOVdNj8Wu',
|
||||
idempotency_key: '2',
|
||||
account_id: '9vmRb29zLQReckr5ay',
|
||||
created_at: (new Date('2020-06-22T18:45:56.000Z'))
|
||||
created_at: new Date('2020-06-22T18:45:56.000Z'),
|
||||
}
|
||||
|
||||
const message3 = {
|
||||
id: '9wLke9zL4Dy4OZR2RM',
|
||||
idempotency_key: '3',
|
||||
account_id: '9vmRb29zLQReckr5ay',
|
||||
created_at: (new Date('2020-07-22T18:45:59.000Z'))
|
||||
created_at: new Date('2020-07-22T18:45:59.000Z'),
|
||||
}
|
||||
|
||||
describe('chatService', () => {
|
||||
|
|
@ -85,7 +85,13 @@ describe('chatService', () => {
|
|||
chatService.add(chat, { messages: [message3] })
|
||||
|
||||
const view = chatService.getView(chat)
|
||||
expect(view.map(i => i.type)).to.eql(['date', 'message', 'message', 'date', 'message'])
|
||||
expect(view.map((i) => i.type)).to.eql([
|
||||
'date',
|
||||
'message',
|
||||
'message',
|
||||
'date',
|
||||
'message',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -95,7 +101,15 @@ describe('chatService', () => {
|
|||
|
||||
for (let i = 100; i > 0; i--) {
|
||||
// Use decimal values with toFixed to hack together constant length predictable strings
|
||||
chatService.add(chat, { messages: [{ ...message1, id: 'a' + (i / 1000).toFixed(3), idempotency_key: i }] })
|
||||
chatService.add(chat, {
|
||||
messages: [
|
||||
{
|
||||
...message1,
|
||||
id: 'a' + (i / 1000).toFixed(3),
|
||||
idempotency_key: i,
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
chatService.cullOlderMessages(chat)
|
||||
expect(chat.messages.length).to.eql(50)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,9 @@
|
|||
import { replaceWord, addPositionToWords, wordAtPosition, splitByWhitespaceBoundary } from '../../../../../src/services/completion/completion.js'
|
||||
import {
|
||||
replaceWord,
|
||||
addPositionToWords,
|
||||
wordAtPosition,
|
||||
splitByWhitespaceBoundary,
|
||||
} from '../../../../../src/services/completion/completion.js'
|
||||
|
||||
describe('addPositiontoWords', () => {
|
||||
it('adds the position to a word list', () => {
|
||||
|
|
@ -8,38 +13,38 @@ describe('addPositiontoWords', () => {
|
|||
{
|
||||
word: 'hey',
|
||||
start: 0,
|
||||
end: 3
|
||||
end: 3,
|
||||
},
|
||||
{
|
||||
word: ' ',
|
||||
start: 3,
|
||||
end: 4
|
||||
end: 4,
|
||||
},
|
||||
{
|
||||
word: 'this',
|
||||
start: 4,
|
||||
end: 8
|
||||
end: 8,
|
||||
},
|
||||
{
|
||||
word: ' ',
|
||||
start: 8,
|
||||
end: 9
|
||||
end: 9,
|
||||
},
|
||||
{
|
||||
word: 'is',
|
||||
start: 9,
|
||||
end: 11
|
||||
end: 11,
|
||||
},
|
||||
{
|
||||
word: ' ',
|
||||
start: 11,
|
||||
end: 12
|
||||
end: 12,
|
||||
},
|
||||
{
|
||||
word: 'fun',
|
||||
start: 12,
|
||||
end: 15
|
||||
}
|
||||
end: 15,
|
||||
},
|
||||
]
|
||||
|
||||
const res = addPositionToWords(words)
|
||||
|
|
@ -51,7 +56,23 @@ describe('addPositiontoWords', () => {
|
|||
describe('splitByWhitespaceBoundary', () => {
|
||||
it('splits at whitespace boundaries', () => {
|
||||
const str = 'This is a #nice @test for you, @idiot@idiot.com'
|
||||
const expected = ['This', ' ', 'is', ' ', 'a', ' ', '#nice', ' ', '@test', ' ', 'for', ' ', 'you,', ' ', '@idiot@idiot.com']
|
||||
const expected = [
|
||||
'This',
|
||||
' ',
|
||||
'is',
|
||||
' ',
|
||||
'a',
|
||||
' ',
|
||||
'#nice',
|
||||
' ',
|
||||
'@test',
|
||||
' ',
|
||||
'for',
|
||||
' ',
|
||||
'you,',
|
||||
' ',
|
||||
'@idiot@idiot.com',
|
||||
]
|
||||
const res = splitByWhitespaceBoundary(str)
|
||||
|
||||
expect(res).to.eql(expected)
|
||||
|
|
|
|||
|
|
@ -1,43 +1,68 @@
|
|||
import * as DateUtils from 'src/services/date_utils/date_utils.js'
|
||||
|
||||
beforeEach(() => { vi.useFakeTimers() })
|
||||
afterEach(() => { vi.useRealTimers() })
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers()
|
||||
})
|
||||
afterEach(() => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
describe('DateUtils', () => {
|
||||
describe('relativeTime', () => {
|
||||
it('returns now with low enough amount of seconds', () => {
|
||||
const futureTime = Date.now() + 20 * DateUtils.SECOND
|
||||
const pastTime = Date.now() - 20 * DateUtils.SECOND
|
||||
expect(DateUtils.relativeTime(futureTime, 30)).to.eql({ num: 0, key: 'time.now' })
|
||||
expect(DateUtils.relativeTime(pastTime, 30)).to.eql({ num: 0, key: 'time.now' })
|
||||
expect(DateUtils.relativeTime(futureTime, 30)).to.eql({
|
||||
num: 0,
|
||||
key: 'time.now',
|
||||
})
|
||||
expect(DateUtils.relativeTime(pastTime, 30)).to.eql({
|
||||
num: 0,
|
||||
key: 'time.now',
|
||||
})
|
||||
})
|
||||
|
||||
it('rounds down for past', () => {
|
||||
const time = Date.now() - 1.8 * DateUtils.HOUR
|
||||
expect(DateUtils.relativeTime(time)).to.eql({ num: 1, key: 'time.unit.hours' })
|
||||
expect(DateUtils.relativeTime(time)).to.eql({
|
||||
num: 1,
|
||||
key: 'time.unit.hours',
|
||||
})
|
||||
})
|
||||
|
||||
it('rounds up for future', () => {
|
||||
const time = Date.now() + 1.8 * DateUtils.HOUR
|
||||
expect(DateUtils.relativeTime(time)).to.eql({ num: 2, key: 'time.unit.hours' })
|
||||
expect(DateUtils.relativeTime(time)).to.eql({
|
||||
num: 2,
|
||||
key: 'time.unit.hours',
|
||||
})
|
||||
})
|
||||
|
||||
it('uses plural when necessary', () => {
|
||||
const time = Date.now() - 3.8 * DateUtils.WEEK
|
||||
expect(DateUtils.relativeTime(time)).to.eql({ num: 3, key: 'time.unit.weeks' })
|
||||
expect(DateUtils.relativeTime(time)).to.eql({
|
||||
num: 3,
|
||||
key: 'time.unit.weeks',
|
||||
})
|
||||
})
|
||||
|
||||
it('works with date string', () => {
|
||||
const time = Date.now() - 4 * DateUtils.MONTH
|
||||
const dateString = new Date(time).toISOString()
|
||||
expect(DateUtils.relativeTime(dateString)).to.eql({ num: 4, key: 'time.unit.months' })
|
||||
expect(DateUtils.relativeTime(dateString)).to.eql({
|
||||
num: 4,
|
||||
key: 'time.unit.months',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('relativeTimeShort', () => {
|
||||
it('returns the short version of the same relative time', () => {
|
||||
const time = Date.now() + 2 * DateUtils.YEAR
|
||||
expect(DateUtils.relativeTimeShort(time)).to.eql({ num: 2, key: 'time.unit.years_short' })
|
||||
expect(DateUtils.relativeTimeShort(time)).to.eql({
|
||||
num: 2,
|
||||
key: 'time.unit.years_short',
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,171 +1,196 @@
|
|||
import { parseStatus, parseUser, parseNotification, parseLinkHeaderPagination } from '../../../../../src/services/entity_normalizer/entity_normalizer.service.js'
|
||||
import {
|
||||
parseStatus,
|
||||
parseUser,
|
||||
parseNotification,
|
||||
parseLinkHeaderPagination,
|
||||
} from '../../../../../src/services/entity_normalizer/entity_normalizer.service.js'
|
||||
import mastoapidata from '../../../../fixtures/mastoapi.json'
|
||||
import qvitterapidata from '../../../../fixtures/statuses.json'
|
||||
|
||||
const makeMockStatusQvitter = (overrides = {}) => {
|
||||
return Object.assign({
|
||||
activity_type: 'post',
|
||||
attachments: [],
|
||||
attentions: [],
|
||||
created_at: 'Tue Jan 15 13:57:56 +0000 2019',
|
||||
external_url: 'https://ap.example/whatever',
|
||||
fave_num: 1,
|
||||
favorited: false,
|
||||
id: '10335970',
|
||||
in_reply_to_ostatus_uri: null,
|
||||
in_reply_to_profileurl: null,
|
||||
in_reply_to_screen_name: null,
|
||||
in_reply_to_status_id: null,
|
||||
in_reply_to_user_id: null,
|
||||
is_local: false,
|
||||
is_post_verb: true,
|
||||
possibly_sensitive: false,
|
||||
repeat_num: 0,
|
||||
repeated: false,
|
||||
statusnet_conversation_id: '16300488',
|
||||
summary: null,
|
||||
tags: [],
|
||||
text: 'haha benis',
|
||||
uri: 'https://ap.example/whatever',
|
||||
user: makeMockUserQvitter(),
|
||||
visibility: 'public'
|
||||
}, overrides)
|
||||
return Object.assign(
|
||||
{
|
||||
activity_type: 'post',
|
||||
attachments: [],
|
||||
attentions: [],
|
||||
created_at: 'Tue Jan 15 13:57:56 +0000 2019',
|
||||
external_url: 'https://ap.example/whatever',
|
||||
fave_num: 1,
|
||||
favorited: false,
|
||||
id: '10335970',
|
||||
in_reply_to_ostatus_uri: null,
|
||||
in_reply_to_profileurl: null,
|
||||
in_reply_to_screen_name: null,
|
||||
in_reply_to_status_id: null,
|
||||
in_reply_to_user_id: null,
|
||||
is_local: false,
|
||||
is_post_verb: true,
|
||||
possibly_sensitive: false,
|
||||
repeat_num: 0,
|
||||
repeated: false,
|
||||
statusnet_conversation_id: '16300488',
|
||||
summary: null,
|
||||
tags: [],
|
||||
text: 'haha benis',
|
||||
uri: 'https://ap.example/whatever',
|
||||
user: makeMockUserQvitter(),
|
||||
visibility: 'public',
|
||||
},
|
||||
overrides,
|
||||
)
|
||||
}
|
||||
|
||||
const makeMockUserQvitter = (overrides = {}) => {
|
||||
return Object.assign({
|
||||
background_image: null,
|
||||
cover_photo: '',
|
||||
created_at: 'Mon Jan 14 13:56:51 +0000 2019',
|
||||
default_scope: 'public',
|
||||
description: 'ebin',
|
||||
description_html: '<p>ebin</p>',
|
||||
favourites_count: 0,
|
||||
fields: [],
|
||||
followers_count: 1,
|
||||
following: true,
|
||||
follows_you: true,
|
||||
friends_count: 1,
|
||||
id: '60717',
|
||||
is_local: false,
|
||||
locked: false,
|
||||
name: 'Spurdo :ebin:',
|
||||
name_html: 'Spurdo <img src="whatever">',
|
||||
no_rich_text: false,
|
||||
pleroma: { confirmation_pending: false, tags: [] },
|
||||
profile_image_url: 'https://ap.example/whatever',
|
||||
profile_image_url_https: 'https://ap.example/whatever',
|
||||
profile_image_url_original: 'https://ap.example/whatever',
|
||||
profile_image_url_profile_size: 'https://ap.example/whatever',
|
||||
rights: { delete_others_notice: false },
|
||||
screen_name: 'spurdo@ap.example',
|
||||
statuses_count: 46,
|
||||
statusnet_blocking: false,
|
||||
statusnet_profile_url: ''
|
||||
}, overrides)
|
||||
return Object.assign(
|
||||
{
|
||||
background_image: null,
|
||||
cover_photo: '',
|
||||
created_at: 'Mon Jan 14 13:56:51 +0000 2019',
|
||||
default_scope: 'public',
|
||||
description: 'ebin',
|
||||
description_html: '<p>ebin</p>',
|
||||
favourites_count: 0,
|
||||
fields: [],
|
||||
followers_count: 1,
|
||||
following: true,
|
||||
follows_you: true,
|
||||
friends_count: 1,
|
||||
id: '60717',
|
||||
is_local: false,
|
||||
locked: false,
|
||||
name: 'Spurdo :ebin:',
|
||||
name_html: 'Spurdo <img src="whatever">',
|
||||
no_rich_text: false,
|
||||
pleroma: { confirmation_pending: false, tags: [] },
|
||||
profile_image_url: 'https://ap.example/whatever',
|
||||
profile_image_url_https: 'https://ap.example/whatever',
|
||||
profile_image_url_original: 'https://ap.example/whatever',
|
||||
profile_image_url_profile_size: 'https://ap.example/whatever',
|
||||
rights: { delete_others_notice: false },
|
||||
screen_name: 'spurdo@ap.example',
|
||||
statuses_count: 46,
|
||||
statusnet_blocking: false,
|
||||
statusnet_profile_url: '',
|
||||
},
|
||||
overrides,
|
||||
)
|
||||
}
|
||||
|
||||
const makeMockUserMasto = (overrides = {}) => {
|
||||
return Object.assign({
|
||||
acct: 'hj',
|
||||
avatar:
|
||||
'https://shigusegubu.club/media/1657b945-8d5b-4ce6-aafb-4c3fc5772120/8ce851029af84d55de9164e30cc7f46d60cbf12eee7e96c5c0d35d9038ddade1.png',
|
||||
avatar_static:
|
||||
'https://shigusegubu.club/media/1657b945-8d5b-4ce6-aafb-4c3fc5772120/8ce851029af84d55de9164e30cc7f46d60cbf12eee7e96c5c0d35d9038ddade1.png',
|
||||
bot: false,
|
||||
created_at: '2017-12-17T21:54:14.000Z',
|
||||
display_name: 'whatever whatever whatever witch',
|
||||
emojis: [],
|
||||
fields: [],
|
||||
followers_count: 705,
|
||||
following_count: 326,
|
||||
header:
|
||||
'https://shigusegubu.club/media/7ab024d9-2a8a-4fbc-9ce8-da06756ae2db/6aadefe4e264133bc377ab450e6b045b6f5458542a5c59e6c741f86107f0388b.png',
|
||||
header_static:
|
||||
'https://shigusegubu.club/media/7ab024d9-2a8a-4fbc-9ce8-da06756ae2db/6aadefe4e264133bc377ab450e6b045b6f5458542a5c59e6c741f86107f0388b.png',
|
||||
id: '1',
|
||||
locked: false,
|
||||
note:
|
||||
'Volatile Internet Weirdo. Name pronounced as Hee Jay. JS and Java dark arts mage, Elixir trainee. I love sampo and lain. Matrix is <span><a data-user="1" href="https://shigusegubu.club/users/hj">@<span>hj</span></a></span>:matrix.heldscal.la Pronouns are whatever. Do not DM me unless it\'s truly private matter and you\'re instance\'s admin or you risk your DM to be reposted publicly.Wish i was Finnish girl.',
|
||||
pleroma: { confirmation_pending: false, tags: null },
|
||||
source: { note: '', privacy: 'public', sensitive: false },
|
||||
statuses_count: 41775,
|
||||
url: 'https://shigusegubu.club/users/hj',
|
||||
username: 'hj'
|
||||
}, overrides)
|
||||
return Object.assign(
|
||||
{
|
||||
acct: 'hj',
|
||||
avatar:
|
||||
'https://shigusegubu.club/media/1657b945-8d5b-4ce6-aafb-4c3fc5772120/8ce851029af84d55de9164e30cc7f46d60cbf12eee7e96c5c0d35d9038ddade1.png',
|
||||
avatar_static:
|
||||
'https://shigusegubu.club/media/1657b945-8d5b-4ce6-aafb-4c3fc5772120/8ce851029af84d55de9164e30cc7f46d60cbf12eee7e96c5c0d35d9038ddade1.png',
|
||||
bot: false,
|
||||
created_at: '2017-12-17T21:54:14.000Z',
|
||||
display_name: 'whatever whatever whatever witch',
|
||||
emojis: [],
|
||||
fields: [],
|
||||
followers_count: 705,
|
||||
following_count: 326,
|
||||
header:
|
||||
'https://shigusegubu.club/media/7ab024d9-2a8a-4fbc-9ce8-da06756ae2db/6aadefe4e264133bc377ab450e6b045b6f5458542a5c59e6c741f86107f0388b.png',
|
||||
header_static:
|
||||
'https://shigusegubu.club/media/7ab024d9-2a8a-4fbc-9ce8-da06756ae2db/6aadefe4e264133bc377ab450e6b045b6f5458542a5c59e6c741f86107f0388b.png',
|
||||
id: '1',
|
||||
locked: false,
|
||||
note: 'Volatile Internet Weirdo. Name pronounced as Hee Jay. JS and Java dark arts mage, Elixir trainee. I love sampo and lain. Matrix is <span><a data-user="1" href="https://shigusegubu.club/users/hj">@<span>hj</span></a></span>:matrix.heldscal.la Pronouns are whatever. Do not DM me unless it\'s truly private matter and you\'re instance\'s admin or you risk your DM to be reposted publicly.Wish i was Finnish girl.',
|
||||
pleroma: { confirmation_pending: false, tags: null },
|
||||
source: { note: '', privacy: 'public', sensitive: false },
|
||||
statuses_count: 41775,
|
||||
url: 'https://shigusegubu.club/users/hj',
|
||||
username: 'hj',
|
||||
},
|
||||
overrides,
|
||||
)
|
||||
}
|
||||
|
||||
const makeMockStatusMasto = (overrides = {}) => {
|
||||
return Object.assign({
|
||||
account: makeMockUserMasto(),
|
||||
application: { name: 'Web', website: null },
|
||||
content:
|
||||
'<span><a data-user="14660" href="https://pleroma.soykaf.com/users/sampo">@<span>sampo</span></a></span> god i wish i was there',
|
||||
created_at: '2019-01-17T16:29:23.000Z',
|
||||
emojis: [],
|
||||
favourited: false,
|
||||
favourites_count: 1,
|
||||
id: '10423476',
|
||||
in_reply_to_account_id: '14660',
|
||||
in_reply_to_id: '10423197',
|
||||
language: null,
|
||||
media_attachments: [],
|
||||
mentions: [
|
||||
{
|
||||
acct: 'sampo@pleroma.soykaf.com',
|
||||
id: '14660',
|
||||
url: 'https://pleroma.soykaf.com/users/sampo',
|
||||
username: 'sampo'
|
||||
}
|
||||
],
|
||||
muted: false,
|
||||
reblog: null,
|
||||
reblogged: false,
|
||||
reblogs_count: 0,
|
||||
replies_count: 0,
|
||||
sensitive: false,
|
||||
spoiler_text: '',
|
||||
tags: [],
|
||||
uri: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639',
|
||||
url: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639',
|
||||
visibility: 'public',
|
||||
pleroma: {
|
||||
local: true
|
||||
}
|
||||
}, overrides)
|
||||
return Object.assign(
|
||||
{
|
||||
account: makeMockUserMasto(),
|
||||
application: { name: 'Web', website: null },
|
||||
content:
|
||||
'<span><a data-user="14660" href="https://pleroma.soykaf.com/users/sampo">@<span>sampo</span></a></span> god i wish i was there',
|
||||
created_at: '2019-01-17T16:29:23.000Z',
|
||||
emojis: [],
|
||||
favourited: false,
|
||||
favourites_count: 1,
|
||||
id: '10423476',
|
||||
in_reply_to_account_id: '14660',
|
||||
in_reply_to_id: '10423197',
|
||||
language: null,
|
||||
media_attachments: [],
|
||||
mentions: [
|
||||
{
|
||||
acct: 'sampo@pleroma.soykaf.com',
|
||||
id: '14660',
|
||||
url: 'https://pleroma.soykaf.com/users/sampo',
|
||||
username: 'sampo',
|
||||
},
|
||||
],
|
||||
muted: false,
|
||||
reblog: null,
|
||||
reblogged: false,
|
||||
reblogs_count: 0,
|
||||
replies_count: 0,
|
||||
sensitive: false,
|
||||
spoiler_text: '',
|
||||
tags: [],
|
||||
uri: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639',
|
||||
url: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639',
|
||||
visibility: 'public',
|
||||
pleroma: {
|
||||
local: true,
|
||||
},
|
||||
},
|
||||
overrides,
|
||||
)
|
||||
}
|
||||
|
||||
const makeMockNotificationQvitter = (overrides = {}) => {
|
||||
return Object.assign({
|
||||
notice: makeMockStatusQvitter(),
|
||||
ntype: 'follow',
|
||||
from_profile: makeMockUserQvitter(),
|
||||
is_seen: 0,
|
||||
id: 123
|
||||
}, overrides)
|
||||
return Object.assign(
|
||||
{
|
||||
notice: makeMockStatusQvitter(),
|
||||
ntype: 'follow',
|
||||
from_profile: makeMockUserQvitter(),
|
||||
is_seen: 0,
|
||||
id: 123,
|
||||
},
|
||||
overrides,
|
||||
)
|
||||
}
|
||||
|
||||
const makeMockEmojiMasto = (overrides = [{}]) => {
|
||||
return [
|
||||
Object.assign({
|
||||
shortcode: 'image',
|
||||
static_url: 'https://example.com/image.png',
|
||||
url: 'https://example.com/image.png',
|
||||
visible_in_picker: false
|
||||
}, overrides[0]),
|
||||
Object.assign({
|
||||
shortcode: 'thinking',
|
||||
static_url: 'https://example.com/think.png',
|
||||
url: 'https://example.com/think.png',
|
||||
visible_in_picker: false
|
||||
}, overrides[1])
|
||||
Object.assign(
|
||||
{
|
||||
shortcode: 'image',
|
||||
static_url: 'https://example.com/image.png',
|
||||
url: 'https://example.com/image.png',
|
||||
visible_in_picker: false,
|
||||
},
|
||||
overrides[0],
|
||||
),
|
||||
Object.assign(
|
||||
{
|
||||
shortcode: 'thinking',
|
||||
static_url: 'https://example.com/think.png',
|
||||
url: 'https://example.com/think.png',
|
||||
visible_in_picker: false,
|
||||
},
|
||||
overrides[1],
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
describe('API Entities normalizer', () => {
|
||||
describe('parseStatus', () => {
|
||||
describe('QVitter preprocessing', () => {
|
||||
it('doesn\'t blow up', () => {
|
||||
it("doesn't blow up", () => {
|
||||
const parsed = qvitterapidata.map(parseStatus)
|
||||
expect(parsed.length).to.eq(qvitterapidata.length)
|
||||
})
|
||||
|
|
@ -173,21 +198,34 @@ describe('API Entities normalizer', () => {
|
|||
it('identifies favorites', () => {
|
||||
const fav = {
|
||||
uri: 'tag:soykaf.com,2016-08-21:fave:2558:note:339495:2016-08-21T16:54:04+00:00',
|
||||
is_post_verb: false
|
||||
is_post_verb: false,
|
||||
}
|
||||
|
||||
const mastoFav = {
|
||||
uri: 'tag:mastodon.social,2016-11-27:objectId=73903:objectType=Favourite',
|
||||
is_post_verb: false
|
||||
is_post_verb: false,
|
||||
}
|
||||
|
||||
expect(parseStatus(makeMockStatusQvitter(fav))).to.have.property('type', 'favorite')
|
||||
expect(parseStatus(makeMockStatusQvitter(mastoFav))).to.have.property('type', 'favorite')
|
||||
expect(parseStatus(makeMockStatusQvitter(fav))).to.have.property(
|
||||
'type',
|
||||
'favorite',
|
||||
)
|
||||
expect(parseStatus(makeMockStatusQvitter(mastoFav))).to.have.property(
|
||||
'type',
|
||||
'favorite',
|
||||
)
|
||||
})
|
||||
|
||||
it('processes repeats correctly', () => {
|
||||
const post = makeMockStatusQvitter({ retweeted_status: null, id: 'deadbeef' })
|
||||
const repeat = makeMockStatusQvitter({ retweeted_status: post, is_post_verb: false, id: 'foobar' })
|
||||
const post = makeMockStatusQvitter({
|
||||
retweeted_status: null,
|
||||
id: 'deadbeef',
|
||||
})
|
||||
const repeat = makeMockStatusQvitter({
|
||||
retweeted_status: post,
|
||||
is_post_verb: false,
|
||||
id: 'foobar',
|
||||
})
|
||||
|
||||
const parsedPost = parseStatus(post)
|
||||
const parsedRepeat = parseStatus(repeat)
|
||||
|
|
@ -195,26 +233,36 @@ describe('API Entities normalizer', () => {
|
|||
expect(parsedPost).to.have.property('type', 'status')
|
||||
expect(parsedRepeat).to.have.property('type', 'retweet')
|
||||
expect(parsedRepeat).to.have.property('retweeted_status')
|
||||
expect(parsedRepeat).to.have.nested.property('retweeted_status.id', 'deadbeef')
|
||||
expect(parsedRepeat).to.have.nested.property(
|
||||
'retweeted_status.id',
|
||||
'deadbeef',
|
||||
)
|
||||
})
|
||||
|
||||
it('sets nsfw for statuses with the #nsfw tag', () => {
|
||||
const safe = makeMockStatusQvitter({ id: '1', text: 'Hello oniichan' })
|
||||
const nsfw = makeMockStatusQvitter({ id: '1', text: 'Hello oniichan #nsfw' })
|
||||
const nsfw = makeMockStatusQvitter({
|
||||
id: '1',
|
||||
text: 'Hello oniichan #nsfw',
|
||||
})
|
||||
|
||||
expect(parseStatus(safe).nsfw).to.eq(false)
|
||||
expect(parseStatus(nsfw).nsfw).to.eq(true)
|
||||
})
|
||||
|
||||
it('leaves existing nsfw settings alone', () => {
|
||||
const nsfw = makeMockStatusQvitter({ id: '1', text: 'Hello oniichan #nsfw', nsfw: false })
|
||||
const nsfw = makeMockStatusQvitter({
|
||||
id: '1',
|
||||
text: 'Hello oniichan #nsfw',
|
||||
nsfw: false,
|
||||
})
|
||||
|
||||
expect(parseStatus(nsfw).nsfw).to.eq(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Mastoapi preprocessing and converting', () => {
|
||||
it('doesn\'t blow up', () => {
|
||||
it("doesn't blow up", () => {
|
||||
const parsed = mastoapidata.map(parseStatus)
|
||||
expect(parsed.length).to.eq(mastoapidata.length)
|
||||
})
|
||||
|
|
@ -229,7 +277,10 @@ describe('API Entities normalizer', () => {
|
|||
expect(parsedPost).to.have.property('type', 'status')
|
||||
expect(parsedRepeat).to.have.property('type', 'retweet')
|
||||
expect(parsedRepeat).to.have.property('retweeted_status')
|
||||
expect(parsedRepeat).to.have.nested.property('retweeted_status.id', 'deadbeef')
|
||||
expect(parsedRepeat).to.have.nested.property(
|
||||
'retweeted_status.id',
|
||||
'deadbeef',
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -245,7 +296,15 @@ describe('API Entities normalizer', () => {
|
|||
})
|
||||
|
||||
it('removes html tags from user profile fields', () => {
|
||||
const user = makeMockUserMasto({ emojis: makeMockEmojiMasto(), fields: [{ name: 'user', value: '<a rel="me" href="https://example.com/@user">@user</a>' }] })
|
||||
const user = makeMockUserMasto({
|
||||
emojis: makeMockEmojiMasto(),
|
||||
fields: [
|
||||
{
|
||||
name: 'user',
|
||||
value: '<a rel="me" href="https://example.com/@user">@user</a>',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const parsedUser = parseUser(user)
|
||||
|
||||
|
|
@ -258,7 +317,14 @@ describe('API Entities normalizer', () => {
|
|||
})
|
||||
|
||||
it('adds hide_follows and hide_followers user settings', () => {
|
||||
const user = makeMockUserMasto({ pleroma: { hide_followers: true, hide_follows: false, hide_followers_count: false, hide_follows_count: true } })
|
||||
const user = makeMockUserMasto({
|
||||
pleroma: {
|
||||
hide_followers: true,
|
||||
hide_follows: false,
|
||||
hide_followers_count: false,
|
||||
hide_follows_count: true,
|
||||
},
|
||||
})
|
||||
|
||||
expect(parseUser(user)).to.have.property('hide_followers', true)
|
||||
expect(parseUser(user)).to.have.property('hide_follows', false)
|
||||
|
|
@ -269,25 +335,38 @@ describe('API Entities normalizer', () => {
|
|||
it('converts IDN to unicode and marks it as internatonal', () => {
|
||||
const user = makeMockUserMasto({ acct: 'lain@xn--lin-6cd.com' })
|
||||
|
||||
expect(parseUser(user)).to.have.property('screen_name_ui').that.equal('lain@lаin.com')
|
||||
expect(parseUser(user)).to.have.property('screen_name_ui_contains_non_ascii').that.equal(true)
|
||||
expect(parseUser(user))
|
||||
.to.have.property('screen_name_ui')
|
||||
.that.equal('lain@lаin.com')
|
||||
expect(parseUser(user))
|
||||
.to.have.property('screen_name_ui_contains_non_ascii')
|
||||
.that.equal(true)
|
||||
})
|
||||
})
|
||||
|
||||
// We currently use QvitterAPI notifications only, and especially due to MastoAPI lacking is_seen, support for MastoAPI
|
||||
// is more of an afterthought
|
||||
describe('parseNotifications (QvitterAPI)', () => {
|
||||
it('correctly normalizes data to FE\'s format', () => {
|
||||
it("correctly normalizes data to FE's format", () => {
|
||||
const notif = makeMockNotificationQvitter({
|
||||
id: 123,
|
||||
notice: makeMockStatusQvitter({ id: 444 }),
|
||||
from_profile: makeMockUserQvitter({ id: 'spurdo' })
|
||||
from_profile: makeMockUserQvitter({ id: 'spurdo' }),
|
||||
})
|
||||
expect(parseNotification(notif)).to.have.property('id', 123)
|
||||
expect(parseNotification(notif)).to.have.property('seen', false)
|
||||
expect(parseNotification(notif)).to.have.nested.property('status.id', '444')
|
||||
expect(parseNotification(notif)).to.have.nested.property('action.id', '444')
|
||||
expect(parseNotification(notif)).to.have.nested.property('from_profile.id', 'spurdo')
|
||||
expect(parseNotification(notif)).to.have.nested.property(
|
||||
'status.id',
|
||||
'444',
|
||||
)
|
||||
expect(parseNotification(notif)).to.have.nested.property(
|
||||
'action.id',
|
||||
'444',
|
||||
)
|
||||
expect(parseNotification(notif)).to.have.nested.property(
|
||||
'from_profile.id',
|
||||
'spurdo',
|
||||
)
|
||||
})
|
||||
|
||||
it('correctly normalizes favorite notifications', () => {
|
||||
|
|
@ -296,36 +375,47 @@ describe('API Entities normalizer', () => {
|
|||
ntype: 'like',
|
||||
notice: makeMockStatusQvitter({
|
||||
id: 444,
|
||||
favorited_status: makeMockStatusQvitter({ id: 4412 })
|
||||
favorited_status: makeMockStatusQvitter({ id: 4412 }),
|
||||
}),
|
||||
is_seen: 1,
|
||||
from_profile: makeMockUserQvitter({ id: 'spurdo' })
|
||||
from_profile: makeMockUserQvitter({ id: 'spurdo' }),
|
||||
})
|
||||
expect(parseNotification(notif)).to.have.property('id', 123)
|
||||
expect(parseNotification(notif)).to.have.property('type', 'like')
|
||||
expect(parseNotification(notif)).to.have.property('seen', true)
|
||||
expect(parseNotification(notif)).to.have.nested.property('status.id', '4412')
|
||||
expect(parseNotification(notif)).to.have.nested.property('action.id', '444')
|
||||
expect(parseNotification(notif)).to.have.nested.property('from_profile.id', 'spurdo')
|
||||
expect(parseNotification(notif)).to.have.nested.property(
|
||||
'status.id',
|
||||
'4412',
|
||||
)
|
||||
expect(parseNotification(notif)).to.have.nested.property(
|
||||
'action.id',
|
||||
'444',
|
||||
)
|
||||
expect(parseNotification(notif)).to.have.nested.property(
|
||||
'from_profile.id',
|
||||
'spurdo',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Link header pagination', () => {
|
||||
it('Parses min and max ids as integers', () => {
|
||||
const linkHeader = '<https://example.com/api/v1/notifications?max_id=861676>; rel="next", <https://example.com/api/v1/notifications?min_id=861741>; rel="prev"'
|
||||
const linkHeader =
|
||||
'<https://example.com/api/v1/notifications?max_id=861676>; rel="next", <https://example.com/api/v1/notifications?min_id=861741>; rel="prev"'
|
||||
const result = parseLinkHeaderPagination(linkHeader)
|
||||
expect(result).to.eql({
|
||||
maxId: 861676,
|
||||
minId: 861741
|
||||
minId: 861741,
|
||||
})
|
||||
})
|
||||
|
||||
it('Parses min and max ids as flakes', () => {
|
||||
const linkHeader = '<http://example.com/api/v1/timelines/home?max_id=9waQx5IIS48qVue2Ai>; rel="next", <http://example.com/api/v1/timelines/home?min_id=9wi61nIPnfn674xgie>; rel="prev"'
|
||||
const linkHeader =
|
||||
'<http://example.com/api/v1/timelines/home?max_id=9waQx5IIS48qVue2Ai>; rel="next", <http://example.com/api/v1/timelines/home?min_id=9wi61nIPnfn674xgie>; rel="prev"'
|
||||
const result = parseLinkHeaderPagination(linkHeader, { flakeId: true })
|
||||
expect(result).to.eql({
|
||||
maxId: '9waQx5IIS48qVue2Ai',
|
||||
minId: '9wi61nIPnfn674xgie'
|
||||
minId: '9wi61nIPnfn674xgie',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,24 +5,24 @@ describe('fileSizeFormat', () => {
|
|||
const expected = [
|
||||
{
|
||||
num: 1,
|
||||
unit: 'B'
|
||||
unit: 'B',
|
||||
},
|
||||
{
|
||||
num: 1,
|
||||
unit: 'KiB'
|
||||
unit: 'KiB',
|
||||
},
|
||||
{
|
||||
num: 1,
|
||||
unit: 'MiB'
|
||||
unit: 'MiB',
|
||||
},
|
||||
{
|
||||
num: 1,
|
||||
unit: 'GiB'
|
||||
unit: 'GiB',
|
||||
},
|
||||
{
|
||||
num: 1,
|
||||
unit: 'TiB'
|
||||
}
|
||||
unit: 'TiB',
|
||||
},
|
||||
]
|
||||
|
||||
const res = []
|
||||
|
|
|
|||
|
|
@ -4,19 +4,21 @@ const mockTouchEvent = (x, y) => ({
|
|||
touches: [
|
||||
{
|
||||
screenX: x,
|
||||
screenY: y
|
||||
}
|
||||
]
|
||||
screenY: y,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
describe('GestureService', () => {
|
||||
describe('swipeGesture', () => {
|
||||
it('calls the callback on a successful swipe', () => {
|
||||
let swiped = false
|
||||
const callback = () => { swiped = true }
|
||||
const callback = () => {
|
||||
swiped = true
|
||||
}
|
||||
const gesture = GestureService.swipeGesture(
|
||||
GestureService.DIRECTION_RIGHT,
|
||||
callback
|
||||
callback,
|
||||
)
|
||||
|
||||
GestureService.beginSwipe(mockTouchEvent(100, 100), gesture)
|
||||
|
|
@ -27,10 +29,12 @@ describe('GestureService', () => {
|
|||
|
||||
it('calls the callback only once per begin', () => {
|
||||
let hits = 0
|
||||
const callback = () => { hits += 1 }
|
||||
const callback = () => {
|
||||
hits += 1
|
||||
}
|
||||
const gesture = GestureService.swipeGesture(
|
||||
GestureService.DIRECTION_RIGHT,
|
||||
callback
|
||||
callback,
|
||||
)
|
||||
|
||||
GestureService.beginSwipe(mockTouchEvent(100, 100), gesture)
|
||||
|
|
@ -40,12 +44,14 @@ describe('GestureService', () => {
|
|||
expect(hits).to.eql(1)
|
||||
})
|
||||
|
||||
it('doesn\'t call the callback on an opposite swipe', () => {
|
||||
it("doesn't call the callback on an opposite swipe", () => {
|
||||
let swiped = false
|
||||
const callback = () => { swiped = true }
|
||||
const callback = () => {
|
||||
swiped = true
|
||||
}
|
||||
const gesture = GestureService.swipeGesture(
|
||||
GestureService.DIRECTION_RIGHT,
|
||||
callback
|
||||
callback,
|
||||
)
|
||||
|
||||
GestureService.beginSwipe(mockTouchEvent(100, 100), gesture)
|
||||
|
|
@ -54,13 +60,15 @@ describe('GestureService', () => {
|
|||
expect(swiped).to.eql(false)
|
||||
})
|
||||
|
||||
it('doesn\'t call the callback on a swipe below threshold', () => {
|
||||
it("doesn't call the callback on a swipe below threshold", () => {
|
||||
let swiped = false
|
||||
const callback = () => { swiped = true }
|
||||
const callback = () => {
|
||||
swiped = true
|
||||
}
|
||||
const gesture = GestureService.swipeGesture(
|
||||
GestureService.DIRECTION_RIGHT,
|
||||
callback,
|
||||
100
|
||||
100,
|
||||
)
|
||||
|
||||
GestureService.beginSwipe(mockTouchEvent(100, 100), gesture)
|
||||
|
|
@ -69,14 +77,16 @@ describe('GestureService', () => {
|
|||
expect(swiped).to.eql(false)
|
||||
})
|
||||
|
||||
it('doesn\'t call the callback on a perpendicular swipe', () => {
|
||||
it("doesn't call the callback on a perpendicular swipe", () => {
|
||||
let swiped = false
|
||||
const callback = () => { swiped = true }
|
||||
const callback = () => {
|
||||
swiped = true
|
||||
}
|
||||
const gesture = GestureService.swipeGesture(
|
||||
GestureService.DIRECTION_RIGHT,
|
||||
callback,
|
||||
30,
|
||||
0.5
|
||||
0.5,
|
||||
)
|
||||
|
||||
GestureService.beginSwipe(mockTouchEvent(100, 100), gesture)
|
||||
|
|
@ -87,12 +97,14 @@ describe('GestureService', () => {
|
|||
|
||||
it('calls the callback on perpendicular swipe if within tolerance', () => {
|
||||
let swiped = false
|
||||
const callback = () => { swiped = true }
|
||||
const callback = () => {
|
||||
swiped = true
|
||||
}
|
||||
const gesture = GestureService.swipeGesture(
|
||||
GestureService.DIRECTION_RIGHT,
|
||||
callback,
|
||||
30,
|
||||
2.0
|
||||
2.0,
|
||||
)
|
||||
|
||||
GestureService.beginSwipe(mockTouchEvent(100, 100), gesture)
|
||||
|
|
@ -103,13 +115,10 @@ describe('GestureService', () => {
|
|||
|
||||
it('works with any arbitrary 2d directions', () => {
|
||||
let swiped = false
|
||||
const callback = () => { swiped = true }
|
||||
const gesture = GestureService.swipeGesture(
|
||||
[-1, -1],
|
||||
callback,
|
||||
30,
|
||||
0.1
|
||||
)
|
||||
const callback = () => {
|
||||
swiped = true
|
||||
}
|
||||
const gesture = GestureService.swipeGesture([-1, -1], callback, 30, 0.1)
|
||||
|
||||
GestureService.beginSwipe(mockTouchEvent(100, 100), gesture)
|
||||
GestureService.updateSwipe(mockTouchEvent(60, 60), gesture)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { convertHtmlToLines } from 'src/services/html_converter/html_line_conver
|
|||
|
||||
const greentextHandle = new Set(['p', 'div'])
|
||||
const mapOnlyText = (processor) => (input) => {
|
||||
if (input.text && input.level.every(l => greentextHandle.has(l))) {
|
||||
if (input.text && input.level.every((l) => greentextHandle.has(l))) {
|
||||
return processor(input.text)
|
||||
} else if (input.text) {
|
||||
return input.text
|
||||
|
|
@ -15,7 +15,8 @@ describe('html_line_converter', () => {
|
|||
describe('with processor that keeps original line should not make any changes to HTML when', () => {
|
||||
const processorKeep = (line) => line
|
||||
it('fed with regular HTML with newlines', () => {
|
||||
const inputOutput = '1<br/>2<p class="lol">3 4</p> 5 \n 6 <p > 7 <br> 8 </p> <br>\n<br/>'
|
||||
const inputOutput =
|
||||
'1<br/>2<p class="lol">3 4</p> 5 \n 6 <p > 7 <br> 8 </p> <br>\n<br/>'
|
||||
const result = convertHtmlToLines(inputOutput)
|
||||
const comparableResult = result.map(mapOnlyText(processorKeep)).join('')
|
||||
expect(comparableResult).to.eql(inputOutput)
|
||||
|
|
@ -35,14 +36,14 @@ describe('html_line_converter', () => {
|
|||
expect(comparableResult).to.eql(inputOutput)
|
||||
})
|
||||
|
||||
it('fed with sorta valid HTML but tags aren\'t closed', () => {
|
||||
it("fed with sorta valid HTML but tags aren't closed", () => {
|
||||
const inputOutput = 'just leaving a <div> hanging'
|
||||
const result = convertHtmlToLines(inputOutput)
|
||||
const comparableResult = result.map(mapOnlyText(processorKeep)).join('')
|
||||
expect(comparableResult).to.eql(inputOutput)
|
||||
})
|
||||
|
||||
it('fed with not really HTML at this point... tags that aren\'t finished', () => {
|
||||
it("fed with not really HTML at this point... tags that aren't finished", () => {
|
||||
const inputOutput = 'do you expect me to finish this <div class='
|
||||
const result = convertHtmlToLines(inputOutput)
|
||||
const comparableResult = result.map(mapOnlyText(processorKeep)).join('')
|
||||
|
|
@ -50,14 +51,16 @@ describe('html_line_converter', () => {
|
|||
})
|
||||
|
||||
it('fed with dubiously valid HTML (p within p and also div inside p)', () => {
|
||||
const inputOutput = 'look ma <p> p \nwithin <p> p! </p> and a <br/><div>div!</div></p>'
|
||||
const inputOutput =
|
||||
'look ma <p> p \nwithin <p> p! </p> and a <br/><div>div!</div></p>'
|
||||
const result = convertHtmlToLines(inputOutput)
|
||||
const comparableResult = result.map(mapOnlyText(processorKeep)).join('')
|
||||
expect(comparableResult).to.eql(inputOutput)
|
||||
})
|
||||
|
||||
it('fed with maybe valid HTML? self-closing divs and ps', () => {
|
||||
const inputOutput = 'a <div class="what"/> what now <p aria-label="wtf"/> ?'
|
||||
const inputOutput =
|
||||
'a <div class="what"/> what now <p aria-label="wtf"/> ?'
|
||||
const result = convertHtmlToLines(inputOutput)
|
||||
const comparableResult = result.map(mapOnlyText(processorKeep)).join('')
|
||||
expect(comparableResult).to.eql(inputOutput)
|
||||
|
|
@ -80,10 +83,13 @@ describe('html_line_converter', () => {
|
|||
describe('with processor that replaces lines with word "_" should match expected line when', () => {
|
||||
const processorReplace = () => '_'
|
||||
it('fed with regular HTML with newlines', () => {
|
||||
const input = '1<br/>2<p class="lol">3 4</p> 5 \n 6 <p > 7 <br> 8 </p> <br>\n<br/>'
|
||||
const input =
|
||||
'1<br/>2<p class="lol">3 4</p> 5 \n 6 <p > 7 <br> 8 </p> <br>\n<br/>'
|
||||
const output = '_<br/>_<p class="lol">_</p>_\n_<p >_<br>_</p> <br>\n<br/>'
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
|
||||
|
|
@ -91,7 +97,9 @@ describe('html_line_converter', () => {
|
|||
const input = '<feeee dwdwddddddw> <i>ayy<b>lm</i>ao</b> </section>'
|
||||
const output = '_'
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
|
||||
|
|
@ -99,31 +107,40 @@ describe('html_line_converter', () => {
|
|||
const input = '</p> lmao what </div> whats going on <div> wha <p>'
|
||||
const output = '_<div>_<p>'
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
|
||||
it('fed with sorta valid HTML but tags aren\'t closed', () => {
|
||||
it("fed with sorta valid HTML but tags aren't closed", () => {
|
||||
const input = 'just leaving a <div> hanging'
|
||||
const output = '_<div>_'
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
|
||||
it('fed with not really HTML at this point... tags that aren\'t finished', () => {
|
||||
it("fed with not really HTML at this point... tags that aren't finished", () => {
|
||||
const input = 'do you expect me to finish this <div class='
|
||||
const output = '_'
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
|
||||
it('fed with dubiously valid HTML (p within p and also div inside p)', () => {
|
||||
const input = 'look ma <p> p \nwithin <p> p! </p> and a <br/><div>div!</div></p>'
|
||||
const input =
|
||||
'look ma <p> p \nwithin <p> p! </p> and a <br/><div>div!</div></p>'
|
||||
const output = '_<p>_\n_<p>_</p>_<br/><div>_</div></p>'
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
|
||||
|
|
@ -131,7 +148,9 @@ describe('html_line_converter', () => {
|
|||
const input = 'a <div class="what"/> what now <p aria-label="wtf"/> ?'
|
||||
const output = '_<div class="what"/>_<p aria-label="wtf"/>_'
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
|
||||
|
|
@ -139,7 +158,9 @@ describe('html_line_converter', () => {
|
|||
const input = 'Yes, it is me, <![CDATA[DIO]]>'
|
||||
const output = '_'
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
|
||||
|
|
@ -153,7 +174,9 @@ describe('html_line_converter', () => {
|
|||
false</code></pre><blockquote>That, christian-like JS diagram but it’s evangelion instead.</blockquote>
|
||||
`
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(input)
|
||||
})
|
||||
it('Testing handling ignored blocks 2', () => {
|
||||
|
|
@ -164,7 +187,9 @@ describe('html_line_converter', () => {
|
|||
<blockquote>An SSL error has happened.</blockquote><p>_</p>
|
||||
`
|
||||
const result = convertHtmlToLines(input)
|
||||
const comparableResult = result.map(mapOnlyText(processorReplace)).join('')
|
||||
const comparableResult = result
|
||||
.map(mapOnlyText(processorReplace))
|
||||
.join('')
|
||||
expect(comparableResult).to.eql(output)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,43 +6,19 @@ describe('html_tree_converter', () => {
|
|||
const input = '1 <p>2</p> <b>3<img src="a">4</b>5'
|
||||
expect(convertHtmlToTree(input)).to.eql([
|
||||
'1 ',
|
||||
[
|
||||
'<p>',
|
||||
['2'],
|
||||
'</p>'
|
||||
],
|
||||
['<p>', ['2'], '</p>'],
|
||||
' ',
|
||||
[
|
||||
'<b>',
|
||||
[
|
||||
'3',
|
||||
['<img src="a">'],
|
||||
'4'
|
||||
],
|
||||
'</b>'
|
||||
],
|
||||
'5'
|
||||
['<b>', ['3', ['<img src="a">'], '4'], '</b>'],
|
||||
'5',
|
||||
])
|
||||
})
|
||||
it('converts html to tree while preserving tag formatting', () => {
|
||||
const input = '1 <p >2</p><b >3<img src="a">4</b>5'
|
||||
expect(convertHtmlToTree(input)).to.eql([
|
||||
'1 ',
|
||||
[
|
||||
'<p >',
|
||||
['2'],
|
||||
'</p>'
|
||||
],
|
||||
[
|
||||
'<b >',
|
||||
[
|
||||
'3',
|
||||
['<img src="a">'],
|
||||
'4'
|
||||
],
|
||||
'</b>'
|
||||
],
|
||||
'5'
|
||||
['<p >', ['2'], '</p>'],
|
||||
['<b >', ['3', ['<img src="a">'], '4'], '</b>'],
|
||||
'5',
|
||||
])
|
||||
})
|
||||
it('converts semi-broken html', () => {
|
||||
|
|
@ -51,14 +27,12 @@ describe('html_tree_converter', () => {
|
|||
'1 ',
|
||||
['<br>'],
|
||||
' 2 ',
|
||||
[
|
||||
'<p>',
|
||||
[' 42']
|
||||
]
|
||||
['<p>', [' 42']],
|
||||
])
|
||||
})
|
||||
it('realistic case 1', () => {
|
||||
const input = '<p><span class="h-card"><a class="u-url mention" data-user="9wRC6T2ZZiKWJ0vUi8" href="https://cawfee.club/users/benis" rel="ugc">@<span>benis</span></a></span> <span class="h-card"><a class="u-url mention" data-user="194" href="https://shigusegubu.club/users/hj" rel="ugc">@<span>hj</span></a></span> nice</p>'
|
||||
const input =
|
||||
'<p><span class="h-card"><a class="u-url mention" data-user="9wRC6T2ZZiKWJ0vUi8" href="https://cawfee.club/users/benis" rel="ugc">@<span>benis</span></a></span> <span class="h-card"><a class="u-url mention" data-user="194" href="https://shigusegubu.club/users/hj" rel="ugc">@<span>hj</span></a></span> nice</p>'
|
||||
expect(convertHtmlToTree(input)).to.eql([
|
||||
[
|
||||
'<p>',
|
||||
|
|
@ -68,20 +42,11 @@ describe('html_tree_converter', () => {
|
|||
[
|
||||
[
|
||||
'<a class="u-url mention" data-user="9wRC6T2ZZiKWJ0vUi8" href="https://cawfee.club/users/benis" rel="ugc">',
|
||||
[
|
||||
'@',
|
||||
[
|
||||
'<span>',
|
||||
[
|
||||
'benis'
|
||||
],
|
||||
'</span>'
|
||||
]
|
||||
],
|
||||
'</a>'
|
||||
]
|
||||
['@', ['<span>', ['benis'], '</span>']],
|
||||
'</a>',
|
||||
],
|
||||
],
|
||||
'</span>'
|
||||
'</span>',
|
||||
],
|
||||
' ',
|
||||
[
|
||||
|
|
@ -89,43 +54,29 @@ describe('html_tree_converter', () => {
|
|||
[
|
||||
[
|
||||
'<a class="u-url mention" data-user="194" href="https://shigusegubu.club/users/hj" rel="ugc">',
|
||||
[
|
||||
'@',
|
||||
[
|
||||
'<span>',
|
||||
[
|
||||
'hj'
|
||||
],
|
||||
'</span>'
|
||||
]
|
||||
],
|
||||
'</a>'
|
||||
]
|
||||
['@', ['<span>', ['hj'], '</span>']],
|
||||
'</a>',
|
||||
],
|
||||
],
|
||||
'</span>'
|
||||
'</span>',
|
||||
],
|
||||
' nice'
|
||||
' nice',
|
||||
],
|
||||
'</p>'
|
||||
]
|
||||
'</p>',
|
||||
],
|
||||
])
|
||||
})
|
||||
it('realistic case 2', () => {
|
||||
const inputOutput = 'Country improv: give me a city<br/>Audience: Memphis<br/>Improv troupe: come on, a better one<br/>Audience: el paso'
|
||||
const inputOutput =
|
||||
'Country improv: give me a city<br/>Audience: Memphis<br/>Improv troupe: come on, a better one<br/>Audience: el paso'
|
||||
expect(convertHtmlToTree(inputOutput)).to.eql([
|
||||
'Country improv: give me a city',
|
||||
[
|
||||
'<br/>'
|
||||
],
|
||||
['<br/>'],
|
||||
'Audience: Memphis',
|
||||
[
|
||||
'<br/>'
|
||||
],
|
||||
['<br/>'],
|
||||
'Improv troupe: come on, a better one',
|
||||
[
|
||||
'<br/>'
|
||||
],
|
||||
'Audience: el paso'
|
||||
['<br/>'],
|
||||
'Audience: el paso',
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import { processTextForEmoji, getAttrs } from 'src/services/html_converter/utility.service.js'
|
||||
import {
|
||||
processTextForEmoji,
|
||||
getAttrs,
|
||||
} from 'src/services/html_converter/utility.service.js'
|
||||
|
||||
describe('html_converter utility', () => {
|
||||
describe('processTextForEmoji', () => {
|
||||
|
|
@ -6,22 +9,22 @@ describe('html_converter utility', () => {
|
|||
const input = 'Hello from finland! :lol: We have best water! :lmao:'
|
||||
const emojis = [
|
||||
{ shortcode: 'lol', src: 'LOL' },
|
||||
{ shortcode: 'lmao', src: 'LMAO' }
|
||||
{ shortcode: 'lmao', src: 'LMAO' },
|
||||
]
|
||||
const processor = ({ shortcode, src }) => ({ shortcode, src })
|
||||
expect(processTextForEmoji(input, emojis, processor)).to.eql([
|
||||
'Hello from finland! ',
|
||||
{ shortcode: 'lol', src: 'LOL' },
|
||||
' We have best water! ',
|
||||
{ shortcode: 'lmao', src: 'LMAO' }
|
||||
{ shortcode: 'lmao', src: 'LMAO' },
|
||||
])
|
||||
})
|
||||
it('leaves text as is', () => {
|
||||
const input = 'Number one: that\'s terror'
|
||||
const input = "Number one: that's terror"
|
||||
const emojis = []
|
||||
const processor = ({ shortcode, src }) => ({ shortcode, src })
|
||||
expect(processTextForEmoji(input, emojis, processor)).to.eql([
|
||||
'Number one: that\'s terror'
|
||||
"Number one: that's terror",
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const localAttn = () => ({
|
|||
is_local: true,
|
||||
name: 'Guy',
|
||||
screen_name: 'person',
|
||||
statusnet_profile_url: 'https://instance.com/users/person'
|
||||
statusnet_profile_url: 'https://instance.com/users/person',
|
||||
})
|
||||
|
||||
const externalAttn = () => ({
|
||||
|
|
@ -13,7 +13,7 @@ const externalAttn = () => ({
|
|||
is_local: false,
|
||||
name: 'Guy',
|
||||
screen_name: 'person@instance.com',
|
||||
statusnet_profile_url: 'https://instance.com/users/person'
|
||||
statusnet_profile_url: 'https://instance.com/users/person',
|
||||
})
|
||||
|
||||
describe('MatcherService', () => {
|
||||
|
|
|
|||
|
|
@ -10,44 +10,46 @@ describe('NotificationUtils', () => {
|
|||
{
|
||||
id: 1,
|
||||
action: { id: '1' },
|
||||
type: 'like'
|
||||
type: 'like',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
action: { id: '2' },
|
||||
type: 'mention'
|
||||
type: 'mention',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
action: { id: '3' },
|
||||
type: 'repeat'
|
||||
}
|
||||
]
|
||||
}
|
||||
type: 'repeat',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
mergedConfig: {
|
||||
notificationVisibility: {
|
||||
likes: true,
|
||||
repeats: true,
|
||||
mentions: false
|
||||
}
|
||||
}
|
||||
}
|
||||
mentions: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
const expected = [
|
||||
{
|
||||
action: { id: '3' },
|
||||
id: 3,
|
||||
type: 'repeat'
|
||||
type: 'repeat',
|
||||
},
|
||||
{
|
||||
action: { id: '1' },
|
||||
id: 1,
|
||||
type: 'like'
|
||||
}
|
||||
type: 'like',
|
||||
},
|
||||
]
|
||||
expect(NotificationUtils.filteredNotificationsFromStore(store)).to.eql(expected)
|
||||
expect(NotificationUtils.filteredNotificationsFromStore(store)).to.eql(
|
||||
expected,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -60,34 +62,36 @@ describe('NotificationUtils', () => {
|
|||
{
|
||||
action: { id: '1' },
|
||||
type: 'like',
|
||||
seen: false
|
||||
seen: false,
|
||||
},
|
||||
{
|
||||
action: { id: '2' },
|
||||
type: 'mention',
|
||||
seen: true
|
||||
}
|
||||
]
|
||||
}
|
||||
seen: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
getters: {
|
||||
mergedConfig: {
|
||||
notificationVisibility: {
|
||||
likes: true,
|
||||
repeats: true,
|
||||
mentions: false
|
||||
}
|
||||
}
|
||||
}
|
||||
mentions: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
const expected = [
|
||||
{
|
||||
action: { id: '1' },
|
||||
type: 'like',
|
||||
seen: false
|
||||
}
|
||||
seen: false,
|
||||
},
|
||||
]
|
||||
expect(NotificationUtils.unseenNotificationsFromStore(store)).to.eql(expected)
|
||||
expect(NotificationUtils.unseenNotificationsFromStore(store)).to.eql(
|
||||
expected,
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,20 +2,25 @@ import { deserialize } from 'src/services/theme_data/iss_deserializer.js'
|
|||
import { serialize } from 'src/services/theme_data/iss_serializer.js'
|
||||
const componentsContext = import.meta.glob(
|
||||
['/src/**/*.style.js', '/src/**/*.style.json'],
|
||||
{ eager: true }
|
||||
{ eager: true },
|
||||
)
|
||||
|
||||
describe('ISS (de)serialization', () => {
|
||||
Object.keys(componentsContext).forEach(key => {
|
||||
Object.keys(componentsContext).forEach((key) => {
|
||||
const component = componentsContext[key].default
|
||||
|
||||
it(`(De)serialization of component ${component.name} works`, () => {
|
||||
const normalized = component.defaultRules.map(x => ({ component: component.name, ...x }))
|
||||
const normalized = component.defaultRules.map((x) => ({
|
||||
component: component.name,
|
||||
...x,
|
||||
}))
|
||||
const serialized = serialize(normalized)
|
||||
const deserialized = deserialize(serialized)
|
||||
|
||||
// for some reason comparing objects directly fails the assert
|
||||
expect(JSON.stringify(deserialized, null, 2)).to.equal(JSON.stringify(normalized, null, 2))
|
||||
expect(JSON.stringify(deserialized, null, 2)).to.equal(
|
||||
JSON.stringify(normalized, null, 2),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const checkColors = (output) => {
|
|||
Object.entries(output.colors).forEach(([key, v]) => {
|
||||
expect(v, key).to.be.an('object')
|
||||
expect(v, key).to.include.all.keys('r', 'g', 'b')
|
||||
'rgba'.split('').forEach(k => {
|
||||
'rgba'.split('').forEach((k) => {
|
||||
if ((k === 'a' && Object.hasOwn(v, 'a')) || k !== 'a') {
|
||||
expect(v[k], key + '.' + k).to.be.a('number')
|
||||
expect(v[k], key + '.' + k).to.be.least(0)
|
||||
|
|
@ -16,7 +16,10 @@ const checkColors = (output) => {
|
|||
}
|
||||
|
||||
describe('Theme Data utility functions', () => {
|
||||
const context = import.meta.glob('/public/static/themes/*.json', { import: 'default', eager: true })
|
||||
const context = import.meta.glob('/public/static/themes/*.json', {
|
||||
import: 'default',
|
||||
eager: true,
|
||||
})
|
||||
Object.keys(context).forEach((key) => {
|
||||
it(`Should render all colors for ${key} properly`, () => {
|
||||
const { theme, source } = context[key]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import { getLayersArray, topoSort } from 'src/services/theme_data/theme_data.service.js'
|
||||
import {
|
||||
getLayersArray,
|
||||
topoSort,
|
||||
} from 'src/services/theme_data/theme_data.service.js'
|
||||
|
||||
describe('Theme Data utility functions', () => {
|
||||
describe('getLayersArray', () => {
|
||||
|
|
@ -6,7 +9,7 @@ describe('Theme Data utility functions', () => {
|
|||
layer1: null,
|
||||
layer2: 'layer1',
|
||||
layer3a: 'layer2',
|
||||
layer3b: 'layer2'
|
||||
layer3b: 'layer2',
|
||||
}
|
||||
|
||||
it('should expand layers properly (3b)', () => {
|
||||
|
|
@ -38,7 +41,7 @@ describe('Theme Data utility functions', () => {
|
|||
layerB: [],
|
||||
layer1B: ['layerB'],
|
||||
layer2B: ['layer1B'],
|
||||
layer3AB: ['layer2B', 'layer2A']
|
||||
layer3AB: ['layer2B', 'layer2A'],
|
||||
}
|
||||
|
||||
// Same thing but messed up order
|
||||
|
|
@ -49,7 +52,7 @@ describe('Theme Data utility functions', () => {
|
|||
layerB: [],
|
||||
layer3AB: ['layer2B', 'layer2A'],
|
||||
layer2B: ['layer1B'],
|
||||
layerA: []
|
||||
layerA: [],
|
||||
}
|
||||
|
||||
it('should make a topologically sorted array', () => {
|
||||
|
|
@ -63,7 +66,7 @@ describe('Theme Data utility functions', () => {
|
|||
expect(out.indexOf('layer2B')).to.be.below(out.indexOf('layer3AB'))
|
||||
})
|
||||
|
||||
it('order in object shouldn\'t matter', () => {
|
||||
it("order in object shouldn't matter", () => {
|
||||
const out = topoSort(fixture2, (node, inheritance) => inheritance[node])
|
||||
// This basically checks all ordering that matters
|
||||
expect(out.indexOf('layerA')).to.be.below(out.indexOf('layer1A'))
|
||||
|
|
@ -82,7 +85,9 @@ describe('Theme Data utility functions', () => {
|
|||
})
|
||||
|
||||
it('ignores cyclic dependencies', () => {
|
||||
const out = topoSort({ a: 'b', b: 'a', c: 'a' }, (node, inheritance) => [inheritance[node]])
|
||||
const out = topoSort({ a: 'b', b: 'a', c: 'a' }, (node, inheritance) => [
|
||||
inheritance[node],
|
||||
])
|
||||
expect(out.indexOf('a')).to.be.below(out.indexOf('c'))
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,62 +1,84 @@
|
|||
import {
|
||||
getAllPossibleCombinations
|
||||
} from 'src/services/theme_data/iss_utils.js'
|
||||
import {
|
||||
init
|
||||
} from 'src/services/theme_data/theme_data_3.service.js'
|
||||
import {
|
||||
basePaletteKeys
|
||||
} from 'src/services/theme_data/theme2_to_theme3.js'
|
||||
import { getAllPossibleCombinations } from 'src/services/theme_data/iss_utils.js'
|
||||
import { init } from 'src/services/theme_data/theme_data_3.service.js'
|
||||
import { basePaletteKeys } from 'src/services/theme_data/theme2_to_theme3.js'
|
||||
|
||||
describe('Theme Data 3', () => {
|
||||
describe('getAllPossibleCombinations', () => {
|
||||
it('test simple 3 values case', () => {
|
||||
const out = getAllPossibleCombinations([1, 2, 3]).map(x => x.sort((a, b) => a - b))
|
||||
expect(out).to.eql([
|
||||
[1], [2], [3],
|
||||
[1, 2], [1, 3], [2, 3],
|
||||
[1, 2, 3]
|
||||
])
|
||||
const out = getAllPossibleCombinations([1, 2, 3]).map((x) =>
|
||||
x.sort((a, b) => a - b),
|
||||
)
|
||||
expect(out).to.eql([[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]])
|
||||
})
|
||||
|
||||
it('test simple 4 values case', () => {
|
||||
const out = getAllPossibleCombinations([1, 2, 3, 4]).map(x => x.sort((a, b) => a - b))
|
||||
const out = getAllPossibleCombinations([1, 2, 3, 4]).map((x) =>
|
||||
x.sort((a, b) => a - b),
|
||||
)
|
||||
expect(out).to.eql([
|
||||
[1], [2], [3], [4],
|
||||
[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4],
|
||||
[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4],
|
||||
[1, 2, 3, 4]
|
||||
[1],
|
||||
[2],
|
||||
[3],
|
||||
[4],
|
||||
[1, 2],
|
||||
[1, 3],
|
||||
[1, 4],
|
||||
[2, 3],
|
||||
[2, 4],
|
||||
[3, 4],
|
||||
[1, 2, 3],
|
||||
[1, 2, 4],
|
||||
[1, 3, 4],
|
||||
[2, 3, 4],
|
||||
[1, 2, 3, 4],
|
||||
])
|
||||
})
|
||||
|
||||
it('test massive 5 values case, using strings', () => {
|
||||
const out = getAllPossibleCombinations(['a', 'b', 'c', 'd', 'e']).map(x => x.sort((a, b) => a - b))
|
||||
const out = getAllPossibleCombinations(['a', 'b', 'c', 'd', 'e']).map(
|
||||
(x) => x.sort((a, b) => a - b),
|
||||
)
|
||||
expect(out).to.eql([
|
||||
// 1
|
||||
['a'], ['b'], ['c'], ['d'], ['e'],
|
||||
['a'],
|
||||
['b'],
|
||||
['c'],
|
||||
['d'],
|
||||
['e'],
|
||||
// 2
|
||||
['a', 'b'], ['a', 'c'], ['a', 'd'], ['a', 'e'],
|
||||
['b', 'c'], ['b', 'd'], ['b', 'e'],
|
||||
['c', 'd'], ['c', 'e'],
|
||||
['a', 'b'],
|
||||
['a', 'c'],
|
||||
['a', 'd'],
|
||||
['a', 'e'],
|
||||
['b', 'c'],
|
||||
['b', 'd'],
|
||||
['b', 'e'],
|
||||
['c', 'd'],
|
||||
['c', 'e'],
|
||||
['d', 'e'],
|
||||
// 3
|
||||
['a', 'b', 'c'], ['a', 'b', 'd'], ['a', 'b', 'e'],
|
||||
['a', 'c', 'd'], ['a', 'c', 'e'],
|
||||
['a', 'b', 'c'],
|
||||
['a', 'b', 'd'],
|
||||
['a', 'b', 'e'],
|
||||
['a', 'c', 'd'],
|
||||
['a', 'c', 'e'],
|
||||
['a', 'd', 'e'],
|
||||
|
||||
['b', 'c', 'd'], ['b', 'c', 'e'],
|
||||
['b', 'c', 'd'],
|
||||
['b', 'c', 'e'],
|
||||
['b', 'd', 'e'],
|
||||
|
||||
['c', 'd', 'e'],
|
||||
// 4
|
||||
['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'e'],
|
||||
['a', 'b', 'c', 'd'],
|
||||
['a', 'b', 'c', 'e'],
|
||||
['a', 'b', 'd', 'e'],
|
||||
|
||||
['a', 'c', 'd', 'e'],
|
||||
|
||||
['b', 'c', 'd', 'e'],
|
||||
// 5
|
||||
['a', 'b', 'c', 'd', 'e']
|
||||
['a', 'b', 'c', 'd', 'e'],
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
@ -76,59 +98,73 @@ describe('Theme Data 3', () => {
|
|||
expect(out.staticVars).to.be.an('object')
|
||||
|
||||
// check backwards compat/generic stuff
|
||||
basePaletteKeys.forEach(key => {
|
||||
basePaletteKeys.forEach((key) => {
|
||||
expect(out.staticVars).to.have.property(key)
|
||||
})
|
||||
})
|
||||
|
||||
it('Test initialization with a basic palette', () => {
|
||||
const out = init({
|
||||
inputRuleset: [{
|
||||
component: 'Root',
|
||||
directives: {
|
||||
'--bg': 'color | #008080',
|
||||
'--fg': 'color | #00C0A0'
|
||||
}
|
||||
}],
|
||||
ultimateBackgroundColor: '#DEADAF'
|
||||
inputRuleset: [
|
||||
{
|
||||
component: 'Root',
|
||||
directives: {
|
||||
'--bg': 'color | #008080',
|
||||
'--fg': 'color | #00C0A0',
|
||||
},
|
||||
},
|
||||
],
|
||||
ultimateBackgroundColor: '#DEADAF',
|
||||
})
|
||||
|
||||
expect(out.staticVars).to.have.property('bg').equal('#008080')
|
||||
expect(out.staticVars).to.have.property('fg').equal('#00C0A0')
|
||||
|
||||
const panelRule = out.eager.filter(x => {
|
||||
const panelRule = out.eager.filter((x) => {
|
||||
if (x.component !== 'Panel') return false
|
||||
return true
|
||||
})[0]
|
||||
|
||||
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked', { r: 0, g: 128, b: 128 })
|
||||
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked', {
|
||||
r: 0,
|
||||
g: 128,
|
||||
b: 128,
|
||||
})
|
||||
})
|
||||
|
||||
it('Test initialization with opacity', () => {
|
||||
const out = init({
|
||||
inputRuleset: [{
|
||||
component: 'Root',
|
||||
directives: {
|
||||
'--bg': 'color | #008080'
|
||||
}
|
||||
}, {
|
||||
component: 'Panel',
|
||||
directives: {
|
||||
opacity: 0.5
|
||||
}
|
||||
}],
|
||||
inputRuleset: [
|
||||
{
|
||||
component: 'Root',
|
||||
directives: {
|
||||
'--bg': 'color | #008080',
|
||||
},
|
||||
},
|
||||
{
|
||||
component: 'Panel',
|
||||
directives: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
},
|
||||
],
|
||||
onlyNormalState: true,
|
||||
ultimateBackgroundColor: '#DEADAF'
|
||||
ultimateBackgroundColor: '#DEADAF',
|
||||
})
|
||||
|
||||
expect(out.staticVars).to.have.property('bg').equal('#008080')
|
||||
|
||||
const panelRule = out.eager.filter(x => {
|
||||
const panelRule = out.eager.filter((x) => {
|
||||
if (x.component !== 'Panel') return false
|
||||
return true
|
||||
})[0]
|
||||
|
||||
expect(panelRule).to.have.nested.deep.property('dynamicVars.background', { r: 0, g: 128, b: 128, a: 0.5 })
|
||||
expect(panelRule).to.have.nested.deep.property('dynamicVars.background', {
|
||||
r: 0,
|
||||
g: 128,
|
||||
b: 128,
|
||||
a: 0.5,
|
||||
})
|
||||
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked')
|
||||
// Somewhat incorrect since we don't do gamma correction
|
||||
// real expectancy should be this:
|
||||
|
|
@ -140,9 +176,15 @@ describe('Theme Data 3', () => {
|
|||
|
||||
*/
|
||||
|
||||
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.r').that.is.closeTo(111, 0.01)
|
||||
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.g').that.is.closeTo(150.5, 0.01)
|
||||
expect(panelRule).to.have.nested.deep.property('dynamicVars.stacked.b').that.is.closeTo(151.5, 0.01)
|
||||
expect(panelRule)
|
||||
.to.have.nested.deep.property('dynamicVars.stacked.r')
|
||||
.that.is.closeTo(111, 0.01)
|
||||
expect(panelRule)
|
||||
.to.have.nested.deep.property('dynamicVars.stacked.g')
|
||||
.that.is.closeTo(150.5, 0.01)
|
||||
expect(panelRule)
|
||||
.to.have.nested.deep.property('dynamicVars.stacked.b')
|
||||
.that.is.closeTo(151.5, 0.01)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,19 +3,22 @@ import generateProfileLink from 'src/services/user_profile_link_generator/user_p
|
|||
describe('generateProfileLink', () => {
|
||||
it('returns obj for local user', () => {
|
||||
expect(generateProfileLink(1, 'jack')).to.eql({
|
||||
name: 'user-profile', params: { name: 'jack' }
|
||||
name: 'user-profile',
|
||||
params: { name: 'jack' },
|
||||
})
|
||||
})
|
||||
|
||||
it('returns obj for external user', () => {
|
||||
expect(generateProfileLink(1, 'john@domain')).to.eql({
|
||||
name: 'external-user-profile', params: { id: 1 }
|
||||
name: 'external-user-profile',
|
||||
params: { id: 1 },
|
||||
})
|
||||
})
|
||||
|
||||
it('returns obj for restricted user', () => {
|
||||
expect(generateProfileLink(1, 'lain', ['lain'])).to.eql({
|
||||
name: 'external-user-profile', params: { id: 1 }
|
||||
name: 'external-user-profile',
|
||||
params: { id: 1 },
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ setActivePinia(createPinia())
|
|||
const store = useListsStore()
|
||||
window.vuex = createStore({
|
||||
modules: {
|
||||
api: apiModule
|
||||
}
|
||||
api: apiModule,
|
||||
},
|
||||
})
|
||||
|
||||
describe('The lists store', () => {
|
||||
|
|
@ -28,12 +28,18 @@ describe('The lists store', () => {
|
|||
const modList = { id: '1', title: 'anotherTestTitle' }
|
||||
|
||||
store.setList({ listId: list.id, title: list.title })
|
||||
expect(store.allListsObject[list.id]).to.eql({ title: list.title, accountIds: [] })
|
||||
expect(store.allListsObject[list.id]).to.eql({
|
||||
title: list.title,
|
||||
accountIds: [],
|
||||
})
|
||||
expect(store.allLists).to.have.length(1)
|
||||
expect(store.allLists[0]).to.eql(list)
|
||||
|
||||
store.setList({ listId: modList.id, title: modList.title })
|
||||
expect(store.allListsObject[modList.id]).to.eql({ title: modList.title, accountIds: [] })
|
||||
expect(store.allListsObject[modList.id]).to.eql({
|
||||
title: modList.title,
|
||||
accountIds: [],
|
||||
})
|
||||
expect(store.allLists).to.have.length(1)
|
||||
expect(store.allLists[0]).to.eql(modList)
|
||||
})
|
||||
|
|
@ -46,16 +52,21 @@ describe('The lists store', () => {
|
|||
store.setListAccounts({ listId: list.id, accountIds: list.accountIds })
|
||||
expect(store.allListsObject[list.id].accountIds).to.eql(list.accountIds)
|
||||
|
||||
store.setListAccounts({ listId: modList.id, accountIds: modList.accountIds })
|
||||
expect(store.allListsObject[modList.id].accountIds).to.eql(modList.accountIds)
|
||||
store.setListAccounts({
|
||||
listId: modList.id,
|
||||
accountIds: modList.accountIds,
|
||||
})
|
||||
expect(store.allListsObject[modList.id].accountIds).to.eql(
|
||||
modList.accountIds,
|
||||
)
|
||||
})
|
||||
|
||||
it('deletes a list', () => {
|
||||
store.$patch({
|
||||
allLists: [{ id: '1', title: 'testList' }],
|
||||
allListsObject: {
|
||||
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
||||
}
|
||||
1: { title: 'testList', accountIds: ['1', '2', '3'] },
|
||||
},
|
||||
})
|
||||
const listId = '1'
|
||||
|
||||
|
|
@ -70,8 +81,8 @@ describe('The lists store', () => {
|
|||
store.$patch({
|
||||
allLists: [{ id: '1', title: 'testList' }],
|
||||
allListsObject: {
|
||||
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
||||
}
|
||||
1: { title: 'testList', accountIds: ['1', '2', '3'] },
|
||||
},
|
||||
})
|
||||
const id = '1'
|
||||
|
||||
|
|
@ -82,8 +93,8 @@ describe('The lists store', () => {
|
|||
store.$patch({
|
||||
allLists: [{ id: '1', title: 'testList' }],
|
||||
allListsObject: {
|
||||
1: { title: 'testList', accountIds: ['1', '2', '3'] }
|
||||
}
|
||||
1: { title: 'testList', accountIds: ['1', '2', '3'] },
|
||||
},
|
||||
})
|
||||
const id = '1'
|
||||
|
||||
|
|
|
|||
|
|
@ -3,16 +3,20 @@ import { createStore } from 'vuex'
|
|||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import { http, HttpResponse } from 'msw'
|
||||
import { useOAuthStore } from 'src/stores/oauth.js'
|
||||
import { injectMswToTest, authApis, testServer } from '/test/fixtures/mock_api.js'
|
||||
import {
|
||||
injectMswToTest,
|
||||
authApis,
|
||||
testServer,
|
||||
} from '/test/fixtures/mock_api.js'
|
||||
|
||||
const test = injectMswToTest(authApis)
|
||||
|
||||
const vuexStore = createStore({
|
||||
modules: {
|
||||
instance: {
|
||||
state: () => ({ server: testServer })
|
||||
}
|
||||
}
|
||||
state: () => ({ server: testServer }),
|
||||
},
|
||||
},
|
||||
})
|
||||
const app = createApp({})
|
||||
app.use(vuexStore)
|
||||
|
|
@ -29,7 +33,6 @@ const getStore = (defaultStateInjection) => {
|
|||
return useOAuthStore()
|
||||
}
|
||||
|
||||
|
||||
describe('createApp', () => {
|
||||
test('it should use create an app and record client id and secret', async () => {
|
||||
const store = getStore()
|
||||
|
|
@ -44,7 +47,7 @@ describe('createApp', () => {
|
|||
worker.use(
|
||||
http.post(`${testServer}/api/v1/apps`, () => {
|
||||
return HttpResponse.text('Throttled', { status: 429 })
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
const store = getStore()
|
||||
|
|
@ -69,12 +72,12 @@ describe('ensureApp', () => {
|
|||
worker.use(
|
||||
http.post(`${testServer}/api/v1/apps`, () => {
|
||||
return HttpResponse.text('Should not call this API', { status: 400 })
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
const store = getStore({
|
||||
clientId: 'another-id',
|
||||
clientSecret: 'another-secret'
|
||||
clientSecret: 'another-secret',
|
||||
})
|
||||
const app = await store.ensureApp()
|
||||
expect(store.clientId).to.eql('another-id')
|
||||
|
|
@ -88,7 +91,7 @@ describe('getAppToken', () => {
|
|||
test('it should get app token and set it in state', async () => {
|
||||
const store = getStore({
|
||||
clientId: 'test-id',
|
||||
clientSecret: 'test-secret'
|
||||
clientSecret: 'test-secret',
|
||||
})
|
||||
const token = await store.getAppToken()
|
||||
expect(token).to.eql('test-app-token')
|
||||
|
|
@ -98,7 +101,7 @@ describe('getAppToken', () => {
|
|||
test('it should throw and not set state if it cannot get app token', async () => {
|
||||
const store = getStore({
|
||||
clientId: 'bad-id',
|
||||
clientSecret: 'bad-secret'
|
||||
clientSecret: 'bad-secret',
|
||||
})
|
||||
await expect(store.getAppToken()).rejects.toThrowError('400')
|
||||
expect(store.appToken).to.eql(false)
|
||||
|
|
@ -115,38 +118,42 @@ describe('ensureAppToken', () => {
|
|||
|
||||
test('it should work if we already have a working token', async () => {
|
||||
const store = getStore({
|
||||
appToken: 'also-good-app-token'
|
||||
appToken: 'also-good-app-token',
|
||||
})
|
||||
const token = await store.ensureAppToken()
|
||||
expect(token).to.eql('also-good-app-token')
|
||||
expect(store.appToken).to.eql('also-good-app-token')
|
||||
})
|
||||
|
||||
test('it should work if we have a bad token but good app credentials', async ({ worker }) => {
|
||||
test('it should work if we have a bad token but good app credentials', async ({
|
||||
worker,
|
||||
}) => {
|
||||
worker.use(
|
||||
http.post(`${testServer}/api/v1/apps`, () => {
|
||||
return HttpResponse.text('Should not call this API', { status: 400 })
|
||||
})
|
||||
}),
|
||||
)
|
||||
const store = getStore({
|
||||
appToken: 'bad-app-token',
|
||||
clientId: 'test-id',
|
||||
clientSecret: 'test-secret'
|
||||
clientSecret: 'test-secret',
|
||||
})
|
||||
const token = await store.ensureAppToken()
|
||||
expect(token).to.eql('test-app-token')
|
||||
expect(store.appToken).to.eql('test-app-token')
|
||||
})
|
||||
|
||||
test('it should work if we have no token but good app credentials', async ({ worker }) => {
|
||||
test('it should work if we have no token but good app credentials', async ({
|
||||
worker,
|
||||
}) => {
|
||||
worker.use(
|
||||
http.post(`${testServer}/api/v1/apps`, () => {
|
||||
return HttpResponse.text('Should not call this API', { status: 400 })
|
||||
})
|
||||
}),
|
||||
)
|
||||
const store = getStore({
|
||||
clientId: 'test-id',
|
||||
clientSecret: 'test-secret'
|
||||
clientSecret: 'test-secret',
|
||||
})
|
||||
const token = await store.ensureAppToken()
|
||||
expect(token).to.eql('test-app-token')
|
||||
|
|
@ -156,7 +163,7 @@ describe('ensureAppToken', () => {
|
|||
test('it should work if we have no token and bad app credentials', async () => {
|
||||
const store = getStore({
|
||||
clientId: 'bad-id',
|
||||
clientSecret: 'bad-secret'
|
||||
clientSecret: 'bad-secret',
|
||||
})
|
||||
const token = await store.ensureAppToken()
|
||||
expect(token).to.eql('test-app-token')
|
||||
|
|
@ -169,7 +176,7 @@ describe('ensureAppToken', () => {
|
|||
const store = getStore({
|
||||
appToken: 'bad-app-token',
|
||||
clientId: 'bad-id',
|
||||
clientSecret: 'bad-secret'
|
||||
clientSecret: 'bad-secret',
|
||||
})
|
||||
const token = await store.ensureAppToken()
|
||||
expect(token).to.eql('test-app-token')
|
||||
|
|
@ -182,7 +189,7 @@ describe('ensureAppToken', () => {
|
|||
worker.use(
|
||||
http.post(`${testServer}/api/v1/apps`, () => {
|
||||
return HttpResponse.text('Throttled', { status: 429 })
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
const store = getStore()
|
||||
|
|
@ -193,7 +200,7 @@ describe('ensureAppToken', () => {
|
|||
worker.use(
|
||||
http.post(`${testServer}/oauth/token`, () => {
|
||||
return HttpResponse.text('Throttled', { status: 429 })
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
const store = getStore()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue