From 4f3a220487c3c8b3596e5a8de7b65cc7c4f0c981 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 8 Mar 2019 22:40:57 +0200 Subject: Since BE doesn't support fetching user by screen name over MastoAPI we'll gonna just fetching it over QvitterAPI real quick :DDDDDDDDD --- test/unit/specs/components/user_profile.spec.js | 3 +-- test/unit/specs/modules/users.spec.js | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/unit/specs/components/user_profile.spec.js b/test/unit/specs/components/user_profile.spec.js index 41fd9cd0..1524c4eb 100644 --- a/test/unit/specs/components/user_profile.spec.js +++ b/test/unit/specs/components/user_profile.spec.js @@ -13,8 +13,7 @@ const mutations = { } const testGetters = { - userByName: state => getters.userByName(state.users), - userById: state => getters.userById(state.users) + findUser: state => getters.findUser(state.users) } const localUser = { diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js index 4d49ee24..dae7e580 100644 --- a/test/unit/specs/modules/users.spec.js +++ b/test/unit/specs/modules/users.spec.js @@ -43,7 +43,7 @@ describe('The users module', () => { } const name = 'Guy' const expected = { screen_name: 'Guy', id: '1' } - expect(getters.userByName(state)(name)).to.eql(expected) + expect(getters.findUser(state)(name)).to.eql(expected) }) it('returns user with matching screen_name with different case', () => { @@ -54,7 +54,7 @@ describe('The users module', () => { } const name = 'Guy' const expected = { screen_name: 'guy', id: '1' } - expect(getters.userByName(state)(name)).to.eql(expected) + expect(getters.findUser(state)(name)).to.eql(expected) }) }) @@ -67,7 +67,7 @@ describe('The users module', () => { } const id = '1' const expected = { screen_name: 'Guy', id: '1' } - expect(getters.userById(state)(id)).to.eql(expected) + expect(getters.findUser(state)(id)).to.eql(expected) }) }) }) -- cgit v1.2.3-70-g09d2 From f3a9200b7c17de04bbedf16cb1ac5d9681ab73f4 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Sat, 9 Mar 2019 02:47:20 +0200 Subject: some test fixes, disabled one test for now since logic now is even more async in general --- test/unit/specs/components/user_profile.spec.js | 3 ++- test/unit/specs/modules/users.spec.js | 31 +++++++++---------------- 2 files changed, 13 insertions(+), 21 deletions(-) (limited to 'test') diff --git a/test/unit/specs/components/user_profile.spec.js b/test/unit/specs/components/user_profile.spec.js index 1524c4eb..23e5ce20 100644 --- a/test/unit/specs/components/user_profile.spec.js +++ b/test/unit/specs/components/user_profile.spec.js @@ -160,7 +160,8 @@ const localProfileStore = new Vuex.Store({ } }) -describe('UserProfile', () => { +// It's a little bit more complicated now +describe.skip('UserProfile', () => { it('renders external profile', () => { const wrapper = mount(UserProfile, { localVue, diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js index dae7e580..a7f18dce 100644 --- a/test/unit/specs/modules/users.spec.js +++ b/test/unit/specs/modules/users.spec.js @@ -34,36 +34,27 @@ describe('The users module', () => { }) }) - describe('getUserByName', () => { + describe('findUser', () => { it('returns user with matching screen_name', () => { + const user = { screen_name: 'Guy', id: '1' } const state = { - users: [ - { screen_name: 'Guy', id: '1' } - ] + usersObject: { + 1: user, + Guy: user + } } const name = 'Guy' const expected = { screen_name: 'Guy', id: '1' } expect(getters.findUser(state)(name)).to.eql(expected) }) - it('returns user with matching screen_name with different case', () => { - const state = { - users: [ - { screen_name: 'guy', id: '1' } - ] - } - const name = 'Guy' - const expected = { screen_name: 'guy', id: '1' } - expect(getters.findUser(state)(name)).to.eql(expected) - }) - }) - - describe('getUserById', () => { it('returns user with matching id', () => { + const user = { screen_name: 'Guy', id: '1' } const state = { - users: [ - { screen_name: 'Guy', id: '1' } - ] + usersObject: { + 1: user, + Guy: user + } } const id = '1' const expected = { screen_name: 'Guy', id: '1' } -- cgit v1.2.3-70-g09d2 From 06d39b62a8358c911b18f5acc378047035840465 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 11 Mar 2019 02:17:49 +0200 Subject: fixed tests, review fixes, now storing local users with downcase screen name for better compatibility --- src/components/user_profile/user_profile.js | 7 ++++--- src/modules/statuses.js | 2 +- src/modules/users.js | 4 ++-- test/unit/specs/components/user_profile.spec.js | 14 ++++++++++---- test/unit/specs/modules/users.spec.js | 4 ++-- 5 files changed, 19 insertions(+), 12 deletions(-) (limited to 'test') diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 2d186bc5..a8dfce2f 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -68,7 +68,7 @@ const UserProfile = { }, userInStore () { const routeParams = this.$route.params - return this.$store.getters.findUser(routeParams.name || routeParams.iid) + return this.$store.getters.findUser(routeParams.name || routeParams.id) }, user () { if (this.timeline.statuses[0]) { @@ -135,13 +135,14 @@ const UserProfile = { } }, watch: { - userId (newVal, oldVal) { + // userId can be undefined if we don't know it yet + userId (newVal) { if (newVal) { this.cleanUp() this.startUp() } }, - userName (newVal, oldVal) { + userName () { if (this.$route.params.name) { this.fetchUserId() this.cleanUp() diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 2b0215f0..ea1b2de0 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -73,7 +73,7 @@ const mergeOrAdd = (arr, obj, item) => { if (oldItem) { // We already have this, so only merge the new info. // We ignore null values to avoid overwriting existing properties with missing data - // we also skip 'used' because that is handled by users module + // we also skip 'user' because that is handled by users module merge(oldItem, omitBy(item, (v, k) => v === null || k === 'user')) // Reactivity fix. oldItem.attachments.splice(oldItem.attachments.length) diff --git a/src/modules/users.js b/src/modules/users.js index e4146c31..5eabb1ec 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -18,7 +18,7 @@ export const mergeOrAdd = (arr, obj, item) => { arr.push(item) obj[item.id] = item if (item.screen_name && !item.screen_name.includes('@')) { - obj[item.screen_name] = item + obj[item.screen_name.toLowerCase()] = item } return { item, new: true } } @@ -132,7 +132,7 @@ export const mutations = { } export const getters = { - findUser: state => query => state.usersObject[query] + findUser: state => query => state.usersObject[typeof query === 'string' ? query.toLowerCase() : query] } export const defaultState = { diff --git a/test/unit/specs/components/user_profile.spec.js b/test/unit/specs/components/user_profile.spec.js index 23e5ce20..847481f3 100644 --- a/test/unit/specs/components/user_profile.spec.js +++ b/test/unit/specs/components/user_profile.spec.js @@ -12,6 +12,11 @@ const mutations = { setError: () => {} } +const actions = { + fetchUser: () => {}, + fetchUserByScreenName: () => {} +} + const testGetters = { findUser: state => getters.findUser(state.users) } @@ -30,6 +35,7 @@ const extUser = { const externalProfileStore = new Vuex.Store({ mutations, + actions, getters: testGetters, state: { api: { @@ -88,7 +94,7 @@ const externalProfileStore = new Vuex.Store({ currentUser: { credentials: '' }, - usersObject: [extUser], + usersObject: { 100: extUser }, users: [extUser] } } @@ -96,6 +102,7 @@ const externalProfileStore = new Vuex.Store({ const localProfileStore = new Vuex.Store({ mutations, + actions, getters: testGetters, state: { api: { @@ -154,14 +161,13 @@ const localProfileStore = new Vuex.Store({ currentUser: { credentials: '' }, - usersObject: [localUser], + usersObject: { 100: localUser, 'testuser': localUser }, users: [localUser] } } }) -// It's a little bit more complicated now -describe.skip('UserProfile', () => { +describe('UserProfile', () => { it('renders external profile', () => { const wrapper = mount(UserProfile, { localVue, diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js index a7f18dce..c8bc0ae7 100644 --- a/test/unit/specs/modules/users.spec.js +++ b/test/unit/specs/modules/users.spec.js @@ -40,7 +40,7 @@ describe('The users module', () => { const state = { usersObject: { 1: user, - Guy: user + guy: user } } const name = 'Guy' @@ -53,7 +53,7 @@ describe('The users module', () => { const state = { usersObject: { 1: user, - Guy: user + guy: user } } const id = '1' -- cgit v1.2.3-70-g09d2 From 4efcda1b4137fa14659a586d4d8559dcdd0f479b Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 11 Mar 2019 22:41:08 +0200 Subject: Added some tests --- .../entity_normalizer/entity_normalizer.service.js | 2 +- .../entity_normalizer/entity_normalizer.spec.js | 75 +++++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js index 633bd3dc..b7e5711e 100644 --- a/src/services/entity_normalizer/entity_normalizer.service.js +++ b/src/services/entity_normalizer/entity_normalizer.service.js @@ -142,7 +142,7 @@ const parseAttachment = (data) => { return output } -const addEmojis = (string, emojis) => { +export const addEmojis = (string, emojis) => { return emojis.reduce((acc, emoji) => { return acc.replace( new RegExp(`:${emoji.shortcode}:`, 'g'), diff --git a/test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js b/test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js index 6245361c..2b0b0d6d 100644 --- a/test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js +++ b/test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js @@ -1,4 +1,4 @@ -import { parseStatus, parseUser, parseNotification } from '../../../../../src/services/entity_normalizer/entity_normalizer.service.js' +import { parseStatus, parseUser, parseNotification, addEmojis } from '../../../../../src/services/entity_normalizer/entity_normalizer.service.js' import mastoapidata from '../../../../fixtures/mastoapi.json' import qvitterapidata from '../../../../fixtures/statuses.json' @@ -143,6 +143,23 @@ const makeMockNotificationQvitter = (overrides = {}) => { }, 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]) + ] +} + parseNotification parseUser parseStatus @@ -218,6 +235,22 @@ describe('API Entities normalizer', () => { expect(parsedRepeat).to.have.property('retweeted_status') expect(parsedRepeat).to.have.deep.property('retweeted_status.id', 'deadbeef') }) + + it('adds emojis to post content', () => { + const post = makeMockStatusMasto({ emojis: makeMockEmojiMasto(), content: 'Makes you think :thinking:' }) + + const parsedPost = parseStatus(post) + + expect(parsedPost).to.have.property('statusnet_html').that.contains(' { + const post = makeMockStatusMasto({ emojis: makeMockEmojiMasto(), spoiler_text: 'CW: 300 IQ :thinking:' }) + + const parsedPost = parseStatus(post) + + expect(parsedPost).to.have.property('summary_html').that.contains(' { expect(parseUser(local)).to.have.property('is_local', true) expect(parseUser(remote)).to.have.property('is_local', false) }) + + it('adds emojis to user name', () => { + const user = makeMockUserMasto({ emojis: makeMockEmojiMasto(), display_name: 'The :thinking: thinker' }) + + const parsedUser = parseUser(user) + + expect(parsedUser).to.have.property('name_html').that.contains(' { + const user = makeMockUserMasto({ emojis: makeMockEmojiMasto(), note: 'Hello i like to :thinking: a lot' }) + + const parsedUser = parseUser(user) + + expect(parsedUser).to.have.property('description_html').that.contains(' { expect(parseNotification(notif)).to.have.deep.property('from_profile.id', 'spurdo') }) }) + + describe('MastoAPI emoji adder', () => { + const emojis = makeMockEmojiMasto() + const imageHtml = 'image' + .replace(/"/g, '\'') + const thinkHtml = 'thinking' + .replace(/"/g, '\'') + + it('correctly replaces shortcodes in supplied string', () => { + const result = addEmojis('This post has :image: emoji and :thinking: emoji', emojis) + expect(result).to.include(thinkHtml) + expect(result).to.include(imageHtml) + }) + + it('handles consecutive emojis correctly', () => { + const result = addEmojis('Lelel emoji spam :thinking::thinking::thinking::thinking:', emojis) + expect(result).to.include(thinkHtml + thinkHtml + thinkHtml + thinkHtml) + }) + + it('Doesn\'t replace nonexistent emojis', () => { + const result = addEmojis('Admin add the :tenshi: emoji', emojis) + expect(result).to.equal('Admin add the :tenshi: emoji') + }) + }) }) -- cgit v1.2.3-70-g09d2 From 06fda2751187233f338a42ec0a3501b2cac2cb62 Mon Sep 17 00:00:00 2001 From: dave Date: Thu, 14 Mar 2019 08:06:40 -0400 Subject: #436: update unit testing --- .../specs/services/notification_utils/notification_utils.spec.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'test') diff --git a/test/unit/specs/services/notification_utils/notification_utils.spec.js b/test/unit/specs/services/notification_utils/notification_utils.spec.js index e945459e..1baa5fc9 100644 --- a/test/unit/specs/services/notification_utils/notification_utils.spec.js +++ b/test/unit/specs/services/notification_utils/notification_utils.spec.js @@ -9,14 +9,17 @@ describe('NotificationUtils', () => { notifications: { data: [ { + id: 1, action: { id: '1' }, type: 'like' }, { + id: 2, action: { id: '2' }, type: 'mention' }, { + id: 3, action: { id: '3' }, type: 'repeat' } @@ -35,10 +38,12 @@ describe('NotificationUtils', () => { const expected = [ { action: { id: '3' }, + id: 3, type: 'repeat' }, { action: { id: '1' }, + id: 1, type: 'like' } ] -- cgit v1.2.3-70-g09d2 From 8ade93bb4db60e04e5e63d533401ee79de403e19 Mon Sep 17 00:00:00 2001 From: dave Date: Thu, 14 Mar 2019 22:36:11 -0400 Subject: #436: update test --- src/components/notifications/notifications.vue | 2 +- test/fixtures/mastoapi.json | 125 ++++++++++++++++----- .../entity_normalizer/entity_normalizer.spec.js | 5 +- 3 files changed, 105 insertions(+), 27 deletions(-) (limited to 'test') diff --git a/src/components/notifications/notifications.vue b/src/components/notifications/notifications.vue index 05f51f6c..37104b90 100644 --- a/src/components/notifications/notifications.vue +++ b/src/components/notifications/notifications.vue @@ -12,7 +12,7 @@
-
+
diff --git a/test/fixtures/mastoapi.json b/test/fixtures/mastoapi.json index 858d7a0d..887fb83e 100644 --- a/test/fixtures/mastoapi.json +++ b/test/fixtures/mastoapi.json @@ -58,7 +58,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639", "url": "https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -127,7 +130,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/6634d32b-96a8-4852-a3db-ac8730715779", "url": "https://shigusegubu.club/objects/6634d32b-96a8-4852-a3db-ac8730715779", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -250,7 +256,10 @@ "tags": [], "uri": "https://pleroma.soykaf.com/objects/bf7e43d4-5048-4176-8519-58e3e1014f8b", "url": "https://pleroma.soykaf.com/objects/bf7e43d4-5048-4176-8519-58e3e1014f8b", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, "reblogged": false, "reblogs_count": 0, @@ -260,7 +269,10 @@ "tags": [], "uri": "https://pleroma.soykaf.com/objects/bf7e43d4-5048-4176-8519-58e3e1014f8b", "url": "https://pleroma.soykaf.com/objects/bf7e43d4-5048-4176-8519-58e3e1014f8b", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -329,7 +341,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/0f963ca1-a263-41ca-a43c-b5d26d0a08e9", "url": "https://shigusegubu.club/objects/0f963ca1-a263-41ca-a43c-b5d26d0a08e9", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -390,7 +405,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/3f809bd8-656f-4a29-81d4-80eed6916eb0", "url": "https://shigusegubu.club/objects/3f809bd8-656f-4a29-81d4-80eed6916eb0", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -516,7 +534,10 @@ }], "uri": "tag:social.super-niche.club,2019-01-17:noticeId=2353002:objectType=note", "url": "https://social.super-niche.club/notice/2353002", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, "reblogged": false, "reblogs_count": 0, @@ -529,7 +550,10 @@ }], "uri": "tag:social.super-niche.club,2019-01-17:noticeId=2353002:objectType=note", "url": "tag:social.super-niche.club,2019-01-17:noticeId=2353002:objectType=note", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -657,7 +681,10 @@ "tags": [], "uri": "https://miniwa.moe/objects/448e2944-0ecd-457f-92c3-cb454f2b0fab", "url": "https://miniwa.moe/objects/448e2944-0ecd-457f-92c3-cb454f2b0fab", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, "reblogged": false, "reblogs_count": 0, @@ -667,7 +694,10 @@ "tags": [], "uri": "https://miniwa.moe/objects/448e2944-0ecd-457f-92c3-cb454f2b0fab", "url": "https://miniwa.moe/objects/448e2944-0ecd-457f-92c3-cb454f2b0fab", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -733,7 +763,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/38b1bc44-15d8-40dd-b1aa-937e0ff4a86d", "url": "https://shigusegubu.club/objects/38b1bc44-15d8-40dd-b1aa-937e0ff4a86d", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -794,7 +827,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/fbff5da4-a517-42a9-bca9-17cae8cf2542", "url": "https://shigusegubu.club/objects/fbff5da4-a517-42a9-bca9-17cae8cf2542", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -850,7 +886,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/4007d659-27c6-4577-be10-fd134f5e4e7e", "url": "https://shigusegubu.club/objects/4007d659-27c6-4577-be10-fd134f5e4e7e", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -906,7 +945,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/59912d51-1cc6-4dc7-828c-f167e6c8b391", "url": "https://shigusegubu.club/objects/59912d51-1cc6-4dc7-828c-f167e6c8b391", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -962,7 +1004,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/62690bce-3f49-4047-9c8e-8941f2f79e10", "url": "https://shigusegubu.club/objects/62690bce-3f49-4047-9c8e-8941f2f79e10", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -1023,7 +1068,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/818f3dd0-2ff8-4def-a170-e4d4c405f387", "url": "https://shigusegubu.club/objects/818f3dd0-2ff8-4def-a170-e4d4c405f387", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -1084,7 +1132,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/0783a193-c097-488d-8944-47df9372cd6e", "url": "https://shigusegubu.club/objects/0783a193-c097-488d-8944-47df9372cd6e", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -1145,7 +1196,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/145d5252-7b8e-467d-9f36-1db0818f452f", "url": "https://shigusegubu.club/objects/145d5252-7b8e-467d-9f36-1db0818f452f", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -1252,7 +1306,10 @@ "tags": [], "uri": "https://pleroma.site/objects/3076c055-0e34-4cf9-86ca-2d148b9b694a", "url": "https://pleroma.site/objects/3076c055-0e34-4cf9-86ca-2d148b9b694a", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, "reblogged": false, "reblogs_count": 0, @@ -1262,7 +1319,10 @@ "tags": [], "uri": "https://pleroma.site/objects/3076c055-0e34-4cf9-86ca-2d148b9b694a", "url": "https://pleroma.site/objects/3076c055-0e34-4cf9-86ca-2d148b9b694a", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -1323,7 +1383,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/d4eb7c46-02f9-4b1f-83af-926cefa21f33", "url": "https://shigusegubu.club/objects/d4eb7c46-02f9-4b1f-83af-926cefa21f33", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -1446,7 +1509,10 @@ "tags": [], "uri": "https://pleroma.soykaf.com/objects/338b6bd2-3c2d-40fe-93a3-28b688782733", "url": "https://pleroma.soykaf.com/objects/338b6bd2-3c2d-40fe-93a3-28b688782733", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, "reblogged": false, "reblogs_count": 0, @@ -1456,7 +1522,10 @@ "tags": [], "uri": "https://pleroma.soykaf.com/objects/338b6bd2-3c2d-40fe-93a3-28b688782733", "url": "https://pleroma.soykaf.com/objects/338b6bd2-3c2d-40fe-93a3-28b688782733", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -1517,7 +1586,10 @@ "tags": [], "uri": "https://shigusegubu.club/objects/f472f4ed-8b0b-492f-9d53-d69eda79629d", "url": "https://shigusegubu.club/objects/f472f4ed-8b0b-492f-9d53-d69eda79629d", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }, { "account": { "acct": "hj", @@ -1578,5 +1650,8 @@ "tags": [], "uri": "https://shigusegubu.club/objects/d6fb4fd2-1f6a-4446-a1a6-5edd34050096", "url": "https://shigusegubu.club/objects/d6fb4fd2-1f6a-4446-a1a6-5edd34050096", - "visibility": "public" + "visibility": "public", + "pleroma": { + "local": true + } }] diff --git a/test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js b/test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js index 6245361c..04bfb953 100644 --- a/test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js +++ b/test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js @@ -129,7 +129,10 @@ const makeMockStatusMasto = (overrides = {}) => { tags: [], uri: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639', url: 'https://shigusegubu.club/objects/16033fbb-97c0-4f0e-b834-7abb92fb8639', - visibility: 'public' + visibility: 'public', + pleroma: { + local: true + } }, overrides) } -- cgit v1.2.3-70-g09d2 From c50e64f8eecd780246e3ac47c2a54164cfc28b8f Mon Sep 17 00:00:00 2001 From: shpuld Date: Tue, 26 Mar 2019 22:11:45 +0200 Subject: Add tests for gesture service, fix bug with perpendicular directions --- src/services/gesture_service/gesture_service.js | 15 +-- .../gesture_service/gesture_service.spec.js | 120 +++++++++++++++++++++ 2 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 test/unit/specs/services/gesture_service/gesture_service.spec.js (limited to 'test') diff --git a/src/services/gesture_service/gesture_service.js b/src/services/gesture_service/gesture_service.js index 2e39003c..efc0ca78 100644 --- a/src/services/gesture_service/gesture_service.js +++ b/src/services/gesture_service/gesture_service.js @@ -10,11 +10,14 @@ const touchEventCoord = e => ([e.touches[0].screenX, e.touches[0].screenY]) const vectorLength = v => Math.sqrt(v[0] * v[0] + v[1] * v[1]) -const perpendicular = v => [v[1], v[0]] +const perpendicular = v => [v[1], -v[0]] const dotProduct = (v1, v2) => v1[0] * v2[0] + v1[1] * v2[1] -const vectorFlatten = (v1, v2) => [v1[0] * v2[0], v1[1] * v2[1]] +const project = (v1, v2) => { + const scalar = (dotProduct(v1, v2) / dotProduct(v2, v2)) + return [scalar * v2[0], scalar * v2[1]] +} // direction: either use the constants above or an arbitrary 2d vector. // threshold: how many Px to move from touch origin before checking if the @@ -46,12 +49,12 @@ const updateSwipe = (event, gesture) => { // movement is opposite from direction if (dotProduct(delta, gesture.direction) < 0) return // movement perpendicular to direction is too much - const towardsDir = vectorFlatten(gesture.direction, delta) + const towardsDir = project(delta, gesture.direction) const perpendicularDir = perpendicular(gesture.direction) - const towardsPerpendicular = vectorFlatten(perpendicularDir, delta) + const towardsPerpendicular = project(delta, perpendicularDir) if ( - vectorLength(towardsDir) < - gesture.perpendicularTolerance * vectorLength(towardsPerpendicular) + vectorLength(towardsDir) * gesture.perpendicularTolerance < + vectorLength(towardsPerpendicular) ) return gesture.onSwipe() diff --git a/test/unit/specs/services/gesture_service/gesture_service.spec.js b/test/unit/specs/services/gesture_service/gesture_service.spec.js new file mode 100644 index 00000000..4a1b009a --- /dev/null +++ b/test/unit/specs/services/gesture_service/gesture_service.spec.js @@ -0,0 +1,120 @@ +import GestureService from 'src/services/gesture_service/gesture_service.js' + +const mockTouchEvent = (x, y) => ({ + touches: [ + { + screenX: x, + screenY: y + } + ] +}) + +describe.only('GestureService', () => { + describe('swipeGesture', () => { + it('calls the callback on a successful swipe', () => { + let swiped = false + const callback = () => { swiped = true } + const gesture = GestureService.swipeGesture( + GestureService.DIRECTION_RIGHT, + callback + ) + + GestureService.beginSwipe(mockTouchEvent(100, 100), gesture) + GestureService.updateSwipe(mockTouchEvent(200, 100), gesture) + + expect(swiped).to.eql(true) + }) + + it('calls the callback only once per begin', () => { + let hits = 0 + const callback = () => { hits += 1 } + const gesture = GestureService.swipeGesture( + GestureService.DIRECTION_RIGHT, + callback + ) + + GestureService.beginSwipe(mockTouchEvent(100, 100), gesture) + GestureService.updateSwipe(mockTouchEvent(150, 100), gesture) + GestureService.updateSwipe(mockTouchEvent(200, 100), gesture) + + expect(hits).to.eql(1) + }) + + it('doesn\'t call the callback on an opposite swipe', () => { + let swiped = false + const callback = () => { swiped = true } + const gesture = GestureService.swipeGesture( + GestureService.DIRECTION_RIGHT, + callback + ) + + GestureService.beginSwipe(mockTouchEvent(100, 100), gesture) + GestureService.updateSwipe(mockTouchEvent(0, 100), gesture) + + expect(swiped).to.eql(false) + }) + + it('doesn\'t call the callback on a swipe below threshold', () => { + let swiped = false + const callback = () => { swiped = true } + const gesture = GestureService.swipeGesture( + GestureService.DIRECTION_RIGHT, + callback, + 100 + ) + + GestureService.beginSwipe(mockTouchEvent(100, 100), gesture) + GestureService.updateSwipe(mockTouchEvent(150, 100), gesture) + + expect(swiped).to.eql(false) + }) + + it('doesn\'t call the callback on a perpendicular swipe', () => { + let swiped = false + const callback = () => { swiped = true } + const gesture = GestureService.swipeGesture( + GestureService.DIRECTION_RIGHT, + callback, + 30, + 0.5 + ) + + GestureService.beginSwipe(mockTouchEvent(100, 100), gesture) + GestureService.updateSwipe(mockTouchEvent(150, 200), gesture) + + expect(swiped).to.eql(false) + }) + + it('calls the callback on perpendicular swipe if within tolerance', () => { + let swiped = false + const callback = () => { swiped = true } + const gesture = GestureService.swipeGesture( + GestureService.DIRECTION_RIGHT, + callback, + 30, + 2.0 + ) + + GestureService.beginSwipe(mockTouchEvent(100, 100), gesture) + GestureService.updateSwipe(mockTouchEvent(150, 150), gesture) + + expect(swiped).to.eql(true) + }) + + it('works with any arbitrary 2d directions', () => { + let swiped = false + 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) + + expect(swiped).to.eql(true) + }) + }) +}) -- cgit v1.2.3-70-g09d2 From 9108737d55300d8a4f822ba94335d8b53f04854d Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Sun, 7 Apr 2019 20:33:11 +0300 Subject: Webpack 4, ESLint with Vue, Node-sass, updated dependencies overall. New linting. --- .eslintrc.js | 12 +- build/utils.js | 75 +- build/webpack.base.conf.js | 76 +- build/webpack.dev.conf.js | 4 +- build/webpack.prod.conf.js | 44 +- package.json | 45 +- src/App.vue | 113 +- src/boot/routes.js | 4 +- src/components/about/about.vue | 6 +- src/components/attachment/attachment.js | 2 +- src/components/attachment/attachment.vue | 100 +- src/components/basic_user_card/basic_user_card.vue | 47 +- src/components/block_card/block_card.vue | 14 +- src/components/chat_panel/chat_panel.js | 2 +- src/components/chat_panel/chat_panel.vue | 59 +- src/components/color_input/color_input.vue | 65 +- src/components/contrast_ratio/contrast_ratio.vue | 52 +- .../conversation-page/conversation-page.vue | 4 +- src/components/conversation/conversation.js | 10 +- src/components/conversation/conversation.vue | 25 +- src/components/delete_button/delete_button.js | 2 +- src/components/delete_button/delete_button.vue | 7 +- src/components/dm_timeline/dm_timeline.vue | 6 +- src/components/emoji-input/emoji-input.js | 5 +- src/components/emoji-input/emoji-input.vue | 41 +- src/components/export_import/export_import.vue | 33 +- src/components/favorite_button/favorite_button.js | 4 +- src/components/favorite_button/favorite_button.vue | 17 +- src/components/features_panel/features_panel.vue | 22 +- src/components/follow_card/follow_card.js | 2 +- src/components/follow_card/follow_card.vue | 19 +- .../follow_request_card/follow_request_card.vue | 14 +- src/components/follow_requests/follow_requests.vue | 8 +- src/components/font_control/font_control.vue | 81 +- .../friends_timeline/friends_timeline.vue | 6 +- src/components/gallery/gallery.vue | 19 +- src/components/image_cropper/image_cropper.vue | 55 +- .../instance_specific_panel.vue | 8 +- .../interface_language_switcher.vue | 52 +- src/components/link-preview/link-preview.vue | 20 +- src/components/login_form/login_form.js | 2 +- src/components/login_form/login_form.vue | 100 +- src/components/media_modal/media_modal.vue | 22 +- src/components/media_upload/media_upload.js | 6 +- src/components/media_upload/media_upload.vue | 30 +- src/components/mentions/mentions.vue | 6 +- src/components/mobile_nav/mobile_nav.vue | 71 +- .../mobile_post_status_modal.vue | 42 +- src/components/mute_card/mute_card.vue | 14 +- src/components/nav_panel/nav_panel.vue | 17 +- src/components/notification/notification.vue | 87 +- src/components/notifications/notifications.vue | 61 +- src/components/oauth_callback/oauth_callback.js | 2 +- src/components/opacity_input/opacity_input.vue | 58 +- .../post_status_form/post_status_form.js | 29 +- .../post_status_form/post_status_form.vue | 260 +- .../public_and_external_timeline.vue | 6 +- src/components/public_timeline/public_timeline.vue | 6 +- src/components/range_input/range_input.vue | 79 +- src/components/registration/registration.js | 4 +- src/components/registration/registration.vue | 225 +- src/components/remote_follow/remote_follow.vue | 22 +- src/components/retweet_button/retweet_button.js | 4 +- src/components/retweet_button/retweet_button.vue | 23 +- src/components/scope_selector/scope_selector.js | 8 +- src/components/scope_selector/scope_selector.vue | 56 +- src/components/settings/settings.vue | 723 ++-- src/components/shadow_control/shadow_control.vue | 293 +- src/components/side_drawer/side_drawer.vue | 92 +- src/components/status/status.js | 8 +- src/components/status/status.vue | 362 +- src/components/still-image/still-image.vue | 18 +- src/components/style_switcher/preview.vue | 151 +- src/components/style_switcher/style_switcher.vue | 827 ++-- src/components/tab_switcher/tab_switcher.js | 40 +- src/components/tag_timeline/tag_timeline.vue | 9 +- .../terms_of_service_panel.vue | 6 +- src/components/timeline/timeline.js | 2 +- src/components/timeline/timeline.vue | 59 +- src/components/user_avatar/user_avatar.vue | 2 +- src/components/user_card/user_card.js | 18 +- src/components/user_card/user_card.vue | 334 +- src/components/user_finder/user_finder.vue | 37 +- src/components/user_panel/user_panel.vue | 16 +- src/components/user_profile/user_profile.vue | 121 +- src/components/user_search/user_search.js | 2 +- src/components/user_search/user_search.vue | 35 +- src/components/user_settings/user_settings.js | 26 +- src/components/user_settings/user_settings.vue | 389 +- .../video_attachment/video_attachment.vue | 5 +- src/components/who_to_follow/who_to_follow.js | 2 +- src/components/who_to_follow/who_to_follow.vue | 8 +- .../who_to_follow_panel/who_to_follow_panel.js | 2 +- .../who_to_follow_panel/who_to_follow_panel.vue | 19 +- src/hocs/with_list/with_list.js | 10 +- src/hocs/with_load_more/with_load_more.js | 56 +- src/hocs/with_subscription/with_subscription.js | 68 +- src/modules/api.js | 10 +- src/modules/chat.js | 4 +- src/modules/config.js | 4 +- src/modules/errors.js | 1 - src/modules/instance.js | 2 +- src/modules/oauth_tokens.js | 4 +- src/modules/statuses.js | 8 +- src/modules/users.js | 24 +- src/services/api/api.service.js | 80 +- .../backend_interactor_service.js | 78 +- src/services/color_convert/color_convert.js | 2 +- src/services/completion/completion.js | 2 +- src/services/file_size_format/file_size_format.js | 2 +- .../follow_request_fetcher.service.js | 2 +- src/services/new_api/oauth.js | 8 +- src/services/new_api/user_search.js | 6 +- src/services/new_api/utils.js | 4 +- .../notification_utils/notification_utils.js | 2 +- .../notifications_fetcher.service.js | 8 +- .../status_poster/status_poster.service.js | 2 +- src/services/style_setter/style_setter.js | 12 +- .../timeline_fetcher/timeline_fetcher.service.js | 10 +- src/services/user_highlighter/user_highlighter.js | 2 +- test/unit/specs/modules/statuses.spec.js | 58 +- test/unit/specs/modules/users.spec.js | 4 +- .../entity_normalizer/entity_normalizer.spec.js | 16 +- .../file_size_format/file_size_format.spec.js | 66 +- .../services/status_parser/status_parses.spec.js | 4 +- yarn.lock | 4092 ++++++++++++++------ 126 files changed, 7326 insertions(+), 3351 deletions(-) (limited to 'test') diff --git a/.eslintrc.js b/.eslintrc.js index 800f9a4f..3c48baa8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,14 +1,17 @@ module.exports = { root: true, - parser: 'babel-eslint', parserOptions: { + parser: 'babel-eslint', sourceType: 'module' }, // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style - extends: 'standard', + extends: [ + 'standard', + 'plugin:vue/recommended' + ], // required to lint *.vue files plugins: [ - 'html' + 'vue' ], // add your custom rules here rules: { @@ -17,6 +20,7 @@ module.exports = { // allow async-await 'generator-star-spacing': 0, // allow debugger during development - 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, + 'vue/require-prop-types': 0 } } diff --git a/build/utils.js b/build/utils.js index 5b90db14..3beee774 100644 --- a/build/utils.js +++ b/build/utils.js @@ -1,61 +1,64 @@ var path = require('path') var config = require('../config') -var ExtractTextPlugin = require('extract-text-webpack-plugin') +var sass = require('sass') +var MiniCssExtractPlugin = require('mini-css-extract-plugin') exports.assetsPath = function (_path) { var assetsSubDirectory = process.env.NODE_ENV === 'production' - ? config.build.assetsSubDirectory - : config.dev.assetsSubDirectory + ? config.build.assetsSubDirectory + : config.dev.assetsSubDirectory return path.posix.join(assetsSubDirectory, _path) } exports.cssLoaders = function (options) { options = options || {} - // generate loader string to be used with extract text plugin - function generateLoaders (loaders) { - var sourceLoader = loaders.map(function (loader) { - var extraParamChar - if (/\?/.test(loader)) { - loader = loader.replace(/\?/, '-loader?') - extraParamChar = '&' - } else { - loader = loader + '-loader' - extraParamChar = '?' - } - return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '') - }).join('!') + function generateLoaders (loaders) { // Extract CSS when that option is specified // (which is the case during production build) if (options.extract) { - return ExtractTextPlugin.extract('vue-style-loader', sourceLoader) + return [MiniCssExtractPlugin.loader].concat(loaders) } else { - return ['vue-style-loader', sourceLoader].join('!') + return ['vue-style-loader'].concat(loaders) } } // http://vuejs.github.io/vue-loader/configurations/extract-css.html - return { - css: generateLoaders(['css']), - postcss: generateLoaders(['css']), - less: generateLoaders(['css', 'less']), - sass: generateLoaders(['css', 'sass?indentedSyntax']), - scss: generateLoaders(['css', 'sass']), - stylus: generateLoaders(['css', 'stylus']), - styl: generateLoaders(['css', 'stylus']) - } + return [ + { + test: /\.(post)?css$/, + use: generateLoaders(['css-loader']), + }, + { + test: /\.less$/, + use: generateLoaders(['css-loader', 'less-loader']), + }, + { + test: /\.sass$/, + use: generateLoaders([ + 'css-loader', + { + loader: 'sass-loader', + options: { + indentedSyntax: true + } + } + ]) + }, + { + test: /\.scss$/, + use: generateLoaders(['css-loader', 'sass-loader']) + }, + { + test: /\.styl(us)?$/, + use: generateLoaders(['css-loader', 'stylus-loader']), + }, + ] } // Generate loaders for standalone style files (outside of .vue) exports.styleLoaders = function (options) { - var output = [] - var loaders = exports.cssLoaders(options) - for (var extension in loaders) { - var loader = loaders[extension] - output.push({ - test: new RegExp('\\.' + extension + '$'), - loader: loader - }) - } + var output = exports.cssLoaders(options) + console.log(output) return output } diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js index e07bb7a2..6f6e785b 100644 --- a/build/webpack.base.conf.js +++ b/build/webpack.base.conf.js @@ -21,8 +21,10 @@ module.exports = { filename: '[name].js' }, resolve: { - extensions: ['', '.js', '.vue'], - fallback: [path.join(__dirname, '../node_modules')], + extensions: ['.js', '.vue'], + modules: [ + path.join(__dirname, '../node_modules') + ], alias: { 'vue$': 'vue/dist/vue.runtime.common', 'src': path.resolve(__dirname, '../src'), @@ -30,67 +32,53 @@ module.exports = { 'components': path.resolve(__dirname, '../src/components') } }, - resolveLoader: { - fallback: [path.join(__dirname, '../node_modules')] - }, module: { noParse: /node_modules\/localforage\/dist\/localforage.js/, - preLoaders: [ + rules: [ { - test: /\.vue$/, - loader: 'eslint', + enforce: 'pre', + test: /\.(js|vue)$/, include: projectRoot, - exclude: /node_modules/ + exclude: /node_modules/, + use: { + loader: 'eslint-loader', + options: { + formatter: require('eslint-friendly-formatter'), + sourceMap: config.build.productionSourceMap, + extract: true + } + } }, - { - test: /\.js$/, - loader: 'eslint', - include: projectRoot, - exclude: /node_modules/ - } - ], - loaders: [ { test: /\.vue$/, - loader: 'vue' + use: 'vue-loader' }, { test: /\.jsx?$/, - loader: 'babel', include: projectRoot, - exclude: /node_modules\/(?!tributejs)/ - }, - { - test: /\.json$/, - loader: 'json' + exclude: /node_modules\/(?!tributejs)/, + use: 'babel-loader' }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, - loader: 'url', - query: { - limit: 10000, - name: utils.assetsPath('img/[name].[hash:7].[ext]') + use: { + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('img/[name].[hash:7].[ext]') + } } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, - loader: 'url', - query: { - limit: 10000, - name: utils.assetsPath('fonts/[name].[hash:7].[ext]') + use: { + loader: 'url-loader', + options: { + limit: 10000, + name: utils.assetsPath('fonts/[name].[hash:7].[ext]') + } } - } - ] - }, - eslint: { - formatter: require('eslint-friendly-formatter') - }, - vue: { - loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }), - postcss: [ - require('autoprefixer')({ - browsers: ['last 2 versions'] - }) + }, ] }, plugins: [ diff --git a/build/webpack.dev.conf.js b/build/webpack.dev.conf.js index 9f34619c..80b87ae8 100644 --- a/build/webpack.dev.conf.js +++ b/build/webpack.dev.conf.js @@ -12,7 +12,7 @@ Object.keys(baseWebpackConfig.entry).forEach(function (name) { module.exports = merge(baseWebpackConfig, { module: { - loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) + rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) }, // eval-source-map is faster for development devtool: '#eval-source-map', @@ -23,9 +23,7 @@ module.exports = merge(baseWebpackConfig, { 'DEV_OVERRIDES': JSON.stringify(config.dev.settings) }), // https://github.com/glenjamin/webpack-hot-middleware#installation--usage - new webpack.optimize.OccurenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), - new webpack.NoErrorsPlugin(), // https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: 'index.html', diff --git a/build/webpack.prod.conf.js b/build/webpack.prod.conf.js index 9699f221..85ea1bee 100644 --- a/build/webpack.prod.conf.js +++ b/build/webpack.prod.conf.js @@ -4,7 +4,7 @@ var utils = require('./utils') var webpack = require('webpack') var merge = require('webpack-merge') var baseWebpackConfig = require('./webpack.base.conf') -var ExtractTextPlugin = require('extract-text-webpack-plugin') +var MiniCssExtractPlugin = require('mini-css-extract-plugin') var HtmlWebpackPlugin = require('html-webpack-plugin') var env = process.env.NODE_ENV === 'testing' ? require('../config/test.env') @@ -13,24 +13,22 @@ var env = process.env.NODE_ENV === 'testing' let commitHash = require('child_process') .execSync('git rev-parse --short HEAD') .toString(); + console.log(commitHash) var webpackConfig = merge(baseWebpackConfig, { module: { - loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) + rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, extract: true }) }, devtool: config.build.productionSourceMap ? '#source-map' : false, + optimization: { + minimize: true + }, output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, - vue: { - loaders: utils.cssLoaders({ - sourceMap: config.build.productionSourceMap, - extract: true - }) - }, plugins: [ // http://vuejs.github.io/vue-loader/workflow/production.html new webpack.DefinePlugin({ @@ -38,14 +36,10 @@ var webpackConfig = merge(baseWebpackConfig, { 'COMMIT_HASH': JSON.stringify(commitHash), 'DEV_OVERRIDES': JSON.stringify(undefined) }), - new webpack.optimize.UglifyJsPlugin({ - compress: { - warnings: false - } - }), - new webpack.optimize.OccurenceOrderPlugin(), // extract css into its own file - new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')), + new MiniCssExtractPlugin({ + filename: utils.assetsPath('css/[name].[contenthash].css') + }), // generate dist index.html with correct asset hash for caching. // you can customize output by editing /index.html // see https://github.com/ampedandwired/html-webpack-plugin @@ -67,25 +61,11 @@ var webpackConfig = merge(baseWebpackConfig, { chunksSortMode: 'dependency' }), // split vendor js into its own file - new webpack.optimize.CommonsChunkPlugin({ - name: 'vendor', - minChunks: function (module, count) { - // any required modules inside node_modules are extracted to vendor - return ( - module.resource && - /\.js$/.test(module.resource) && - module.resource.indexOf( - path.join(__dirname, '../node_modules') - ) === 0 - ) - } - }), // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated - new webpack.optimize.CommonsChunkPlugin({ - name: 'manifest', - chunks: ['vendor'] - }) + // new webpack.optimize.SplitChunksPlugin({ + // name: ['app', 'vendor'] + // }), ] }) diff --git a/package.json b/package.json index 03228133..a9024d7e 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "unit:watch": "karma start test/unit/karma.conf.js --single-run=false", "e2e": "node test/e2e/runner.js", "test": "npm run unit && npm run e2e", - "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs" + "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs", + "lint-fix": "eslint --fix --ext .js,.vue src test/unit/specs test/e2e/specs" }, "dependencies": { "babel-plugin-add-module-exports": "^0.2.1", @@ -21,11 +22,9 @@ "diff": "^3.0.1", "karma-mocha-reporter": "^2.2.1", "localforage": "^1.5.0", - "node-sass": "^3.10.1", "object-path": "^0.11.3", "phoenix": "^1.3.0", "sanitize-html": "^1.13.0", - "sass-loader": "^4.0.2", "vue": "^2.5.13", "vue-chat-scroll": "^1.2.1", "vue-compose": "^0.7.1", @@ -44,7 +43,7 @@ "babel-core": "^6.0.0", "babel-eslint": "^7.0.0", "babel-helper-vue-jsx-merge-props": "^2.0.3", - "babel-loader": "^6.0.0", + "babel-loader": "^7.0.0", "babel-plugin-syntax-jsx": "^6.18.0", "babel-plugin-transform-runtime": "^6.0.0", "babel-plugin-transform-vue-jsx": "3", @@ -57,20 +56,21 @@ "chromedriver": "^2.21.2", "connect-history-api-fallback": "^1.1.0", "cross-spawn": "^4.0.2", - "css-loader": "^0.25.0", - "eslint": "^3.7.1", - "eslint-config-standard": "^6.1.0", + "css-loader": "^0.28.0", + "eslint": "^5.16.0", + "eslint-config-standard": "^12.0.0", "eslint-friendly-formatter": "^2.0.5", - "eslint-loader": "^1.5.0", - "eslint-plugin-html": "^1.5.5", - "eslint-plugin-promise": "^2.0.1", - "eslint-plugin-standard": "^2.0.1", + "eslint-loader": "^2.1.0", + "eslint-plugin-import": "^2.13.0", + "eslint-plugin-node": "^7.0.0", + "eslint-plugin-promise": "^4.0.0", + "eslint-plugin-standard": "^4.0.0", + "eslint-plugin-vue": "^5.2.2", "eventsource-polyfill": "^0.9.6", "express": "^4.13.3", - "extract-text-webpack-plugin": "^1.0.1", - "file-loader": "^0.9.0", + "file-loader": "^3.0.1", "function-bind": "^1.0.2", - "html-webpack-plugin": "^2.8.1", + "html-webpack-plugin": "^3.0.0", "http-proxy-middleware": "^0.17.2", "inject-loader": "^2.0.1", "iso-639-1": "^2.0.3", @@ -83,26 +83,29 @@ "karma-sinon-chai": "^1.2.0", "karma-sourcemap-loader": "^0.3.7", "karma-spec-reporter": "0.0.26", - "karma-webpack": "^1.7.0", + "karma-webpack": "git://github.com/webpack-contrib/karma-webpack.git#v4.0.0-rc.3", "lodash": "^4.16.4", "lolex": "^1.4.0", + "mini-css-extract-plugin": "^0.5.0", "mocha": "^3.1.0", "nightwatch": "^0.9.8", "opn": "^4.0.2", "ora": "^0.3.0", "phantomjs-prebuilt": "^2.1.3", "raw-loader": "^0.5.1", + "sass": "^1.17.3", + "sass-loader": "git://github.com/webpack-contrib/sass-loader", "selenium-server": "2.53.1", "semver": "^5.3.0", - "serviceworker-webpack-plugin": "0.2.3", + "serviceworker-webpack-plugin": "^1.0.0", "shelljs": "^0.7.4", "sinon": "^1.17.3", "sinon-chai": "^2.8.0", - "url-loader": "^0.5.7", - "vue-loader": "^11.1.0", - "vue-style-loader": "^2.0.0", - "webpack": "^1.13.2", - "webpack-dev-middleware": "^1.8.3", + "url-loader": "^1.1.2", + "vue-loader": "^14.0.0", + "vue-style-loader": "^4.0.0", + "webpack": "^4.0.0", + "webpack-dev-middleware": "^3.6.0", "webpack-hot-middleware": "^2.12.2", "webpack-merge": "^0.14.1" }, diff --git a/src/App.vue b/src/App.vue index 3b8623ad..e1f6b4a5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,51 +1,112 @@ diff --git a/src/boot/routes.js b/src/boot/routes.js index 7e54a98b..3538c1e6 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -24,8 +24,8 @@ export default (store) => { path: '/', redirect: _to => { return (store.state.users.currentUser - ? store.state.instance.redirectRootLogin - : store.state.instance.redirectRootNoLogin) || '/main/all' + ? store.state.instance.redirectRootLogin + : store.state.instance.redirectRootNoLogin) || '/main/all' } }, { name: 'public-external-timeline', path: '/main/all', component: PublicAndExternalTimeline }, diff --git a/src/components/about/about.vue b/src/components/about/about.vue index 13dec87c..62ae16ea 100644 --- a/src/components/about/about.vue +++ b/src/components/about/about.vue @@ -1,8 +1,8 @@ diff --git a/src/components/attachment/attachment.js b/src/components/attachment/attachment.js index 3b7f08dc..e93921fe 100644 --- a/src/components/attachment/attachment.js +++ b/src/components/attachment/attachment.js @@ -51,7 +51,7 @@ const Attachment = { } }, methods: { - linkClicked ({target}) { + linkClicked ({ target }) { if (target.tagName === 'A') { window.open(target.href, '_blank') } diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index c58bebd3..12ed9158 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -1,54 +1,104 @@