diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/e2e/nightwatch.conf.js | 54 | ||||
| -rw-r--r-- | test/fixtures/mastoapi.json | 125 | ||||
| -rw-r--r-- | test/unit/index.js | 8 | ||||
| -rw-r--r-- | test/unit/karma.conf.js | 17 | ||||
| -rw-r--r-- | test/unit/specs/components/emoji_input.spec.js | 131 | ||||
| -rw-r--r-- | test/unit/specs/components/timeline.spec.js | 27 | ||||
| -rw-r--r-- | test/unit/specs/components/user_profile.spec.js | 16 | ||||
| -rw-r--r-- | test/unit/specs/modules/statuses.spec.js | 62 | ||||
| -rw-r--r-- | test/unit/specs/modules/users.spec.js | 39 | ||||
| -rw-r--r-- | test/unit/specs/services/date_utils/date_utils.spec.js | 40 | ||||
| -rw-r--r-- | test/unit/specs/services/entity_normalizer/entity_normalizer.spec.js | 110 | ||||
| -rw-r--r-- | test/unit/specs/services/file_size_format/file_size_format.spec.js | 66 | ||||
| -rw-r--r-- | test/unit/specs/services/gesture_service/gesture_service.spec.js | 120 | ||||
| -rw-r--r-- | test/unit/specs/services/notification_utils/notification_utils.spec.js | 5 | ||||
| -rw-r--r-- | test/unit/specs/services/status_parser/status_parses.spec.js | 4 | ||||
| -rw-r--r-- | test/unit/specs/services/version/version.service.spec.js | 11 |
16 files changed, 668 insertions, 167 deletions
diff --git a/test/e2e/nightwatch.conf.js b/test/e2e/nightwatch.conf.js index a5e55e90..2fc3af0b 100644 --- a/test/e2e/nightwatch.conf.js +++ b/test/e2e/nightwatch.conf.js @@ -3,43 +3,43 @@ var config = require('../../config') // http://nightwatchjs.org/guide#settings-file module.exports = { - "src_folders": ["test/e2e/specs"], - "output_folder": "test/e2e/reports", - "custom_assertions_path": ["test/e2e/custom-assertions"], + 'src_folders': ['test/e2e/specs'], + 'output_folder': 'test/e2e/reports', + 'custom_assertions_path': ['test/e2e/custom-assertions'], - "selenium": { - "start_process": true, - "server_path": "node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar", - "host": "127.0.0.1", - "port": 4444, - "cli_args": { - "webdriver.chrome.driver": require('chromedriver').path + 'selenium': { + 'start_process': true, + 'server_path': 'node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.1.jar', + 'host': '127.0.0.1', + 'port': 4444, + 'cli_args': { + 'webdriver.chrome.driver': require('chromedriver').path } }, - "test_settings": { - "default": { - "selenium_port": 4444, - "selenium_host": "localhost", - "silent": true, - "globals": { - "devServerURL": "http://localhost:" + (process.env.PORT || config.dev.port) + 'test_settings': { + 'default': { + 'selenium_port': 4444, + 'selenium_host': 'localhost', + 'silent': true, + 'globals': { + 'devServerURL': 'http://localhost:' + (process.env.PORT || config.dev.port) } }, - "chrome": { - "desiredCapabilities": { - "browserName": "chrome", - "javascriptEnabled": true, - "acceptSslCerts": true + 'chrome': { + 'desiredCapabilities': { + 'browserName': 'chrome', + 'javascriptEnabled': true, + 'acceptSslCerts': true } }, - "firefox": { - "desiredCapabilities": { - "browserName": "firefox", - "javascriptEnabled": true, - "acceptSslCerts": true + 'firefox': { + 'desiredCapabilities': { + 'browserName': 'firefox', + 'javascriptEnabled': true, + 'acceptSslCerts': true } } } 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/index.js b/test/unit/index.js index 03b19e32..83a2dcdb 100644 --- a/test/unit/index.js +++ b/test/unit/index.js @@ -1,7 +1,3 @@ -// Polyfill fn.bind() for PhantomJS -/* eslint-disable no-extend-native */ -Function.prototype.bind = require('function-bind') - // require all test files (files that ends with .spec.js) const testsContext = require.context('./specs', true, /\.spec$/) testsContext.keys().forEach(testsContext) @@ -9,5 +5,5 @@ testsContext.keys().forEach(testsContext) // require all src files except main.js for coverage. // you can also change this to match only the subset of files that // you want coverage for. -const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) -srcContext.keys().forEach(srcContext) +// const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) +// srcContext.keys().forEach(srcContext) diff --git a/test/unit/karma.conf.js b/test/unit/karma.conf.js index d19a2229..8af05c24 100644 --- a/test/unit/karma.conf.js +++ b/test/unit/karma.conf.js @@ -3,17 +3,17 @@ // we are also using it with karma-webpack // https://github.com/webpack/karma-webpack -var path = require('path') +// var path = require('path') var merge = require('webpack-merge') var baseConfig = require('../../build/webpack.base.conf') var utils = require('../../build/utils') var webpack = require('webpack') -var projectRoot = path.resolve(__dirname, '../../') +// var projectRoot = path.resolve(__dirname, '../../') var webpackConfig = merge(baseConfig, { // use inline sourcemap for karma-sourcemap-loader module: { - loaders: utils.styleLoaders() + rules: utils.styleLoaders() }, devtool: '#inline-source-map', // vue: { @@ -53,11 +53,18 @@ module.exports = function (config) { // 1. install corresponding karma launcher // http://karma-runner.github.io/0.13/config/browsers.html // 2. add it to the `browsers` array below. - browsers: ['PhantomJS'], + browsers: ['FirefoxHeadless'], frameworks: ['mocha', 'sinon-chai'], reporters: ['mocha'], + customLaunchers: { + 'FirefoxHeadless': { + base: 'Firefox', + flags: [ + '-headless' + ] + } + }, files: [ - '../../node_modules/@babel/polyfill/dist/polyfill.js', './index.js' ], preprocessors: { diff --git a/test/unit/specs/components/emoji_input.spec.js b/test/unit/specs/components/emoji_input.spec.js new file mode 100644 index 00000000..368d623d --- /dev/null +++ b/test/unit/specs/components/emoji_input.spec.js @@ -0,0 +1,131 @@ +import { shallowMount, createLocalVue } from '@vue/test-utils' +import EmojiInput from 'src/components/emoji_input/emoji_input.vue' + +const generateInput = (value, padEmoji = true) => { + const localVue = createLocalVue() + localVue.directive('click-outside', () => {}) + const wrapper = shallowMount(EmojiInput, { + propsData: { + suggest: () => [], + enableEmojiPicker: true, + value + }, + mocks: { + $store: { + state: { + config: { + padEmoji + } + } + } + }, + slots: { + default: '<input />' + }, + localVue + }) + return [wrapper, localVue] +} + +describe('EmojiInput', () => { + describe('insertion mechanism', () => { + it('inserts string at the end with trailing space', () => { + const initialString = 'Testing' + const [wrapper] = generateInput(initialString) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: initialString.length }) + wrapper.vm.insert({ insertion: '(test)', keepOpen: false }) + expect(wrapper.emitted().input[0][0]).to.eql('Testing (test) ') + }) + + it('inserts string at the end with trailing space (source has a trailing space)', () => { + const initialString = 'Testing ' + const [wrapper] = generateInput(initialString) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: initialString.length }) + wrapper.vm.insert({ insertion: '(test)', keepOpen: false }) + expect(wrapper.emitted().input[0][0]).to.eql('Testing (test) ') + }) + + it('inserts string at the begginning without leading space', () => { + const initialString = 'Testing' + const [wrapper] = generateInput(initialString) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: 0 }) + wrapper.vm.insert({ insertion: '(test)', keepOpen: false }) + expect(wrapper.emitted().input[0][0]).to.eql('(test) Testing') + }) + + it('inserts string between words without creating extra spaces', () => { + const initialString = 'Spurdo Sparde' + const [wrapper] = generateInput(initialString) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: 6 }) + wrapper.vm.insert({ insertion: ':ebin:', keepOpen: false }) + expect(wrapper.emitted().input[0][0]).to.eql('Spurdo :ebin: Sparde') + }) + + it('inserts string between words without creating extra spaces (other caret)', () => { + const initialString = 'Spurdo Sparde' + const [wrapper] = generateInput(initialString) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: 7 }) + wrapper.vm.insert({ insertion: ':ebin:', keepOpen: false }) + expect(wrapper.emitted().input[0][0]).to.eql('Spurdo :ebin: Sparde') + }) + + it('inserts string without any padding if padEmoji setting is set to false', () => { + const initialString = 'Eat some spam!' + const [wrapper] = generateInput(initialString, false) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: initialString.length, keepOpen: false }) + wrapper.vm.insert({ insertion: ':spam:' }) + expect(wrapper.emitted().input[0][0]).to.eql('Eat some spam!:spam:') + }) + + it('correctly sets caret after insertion at beginning', (done) => { + const initialString = '1234' + const [wrapper, vue] = generateInput(initialString) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: 0 }) + wrapper.vm.insert({ insertion: '1234', keepOpen: false }) + vue.nextTick(() => { + expect(wrapper.vm.caret).to.eql(5) + done() + }) + }) + + it('correctly sets caret after insertion at end', (done) => { + const initialString = '1234' + const [wrapper, vue] = generateInput(initialString) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: initialString.length }) + wrapper.vm.insert({ insertion: '1234', keepOpen: false }) + vue.nextTick(() => { + expect(wrapper.vm.caret).to.eql(10) + done() + }) + }) + + it('correctly sets caret after insertion if padEmoji setting is set to false', (done) => { + const initialString = '1234' + const [wrapper, vue] = generateInput(initialString, false) + const input = wrapper.find('input') + input.setValue(initialString) + wrapper.setData({ caret: initialString.length }) + wrapper.vm.insert({ insertion: '1234', keepOpen: false }) + vue.nextTick(() => { + expect(wrapper.vm.caret).to.eql(8) + done() + }) + }) + }) +}) diff --git a/test/unit/specs/components/timeline.spec.js b/test/unit/specs/components/timeline.spec.js new file mode 100644 index 00000000..0c8674a8 --- /dev/null +++ b/test/unit/specs/components/timeline.spec.js @@ -0,0 +1,27 @@ +import { getExcludedStatusIdsByPinning } from 'src/components/timeline/timeline.js' + +describe('Timeline', () => { + describe('getExcludedStatusIdsByPinning', () => { + const mockStatuses = (ids) => ids.map(id => ({ id })) + + it('should return only members of both pinnedStatusIds and ids of the given statuses', () => { + const statusIds = [1, 2, 3, 4] + const statuses = mockStatuses(statusIds) + const pinnedStatusIds = [1, 3, 5] + const result = getExcludedStatusIdsByPinning(statuses, pinnedStatusIds) + result.forEach(item => { + expect(item).to.be.oneOf(statusIds) + expect(item).to.be.oneOf(pinnedStatusIds) + }) + }) + + it('should return ids of pinned statuses not posted before any unpinned status', () => { + const pinnedStatusIdSet1 = ['PINNED1', 'PINNED2'] + const pinnedStatusIdSet2 = ['PINNED3', 'PINNED4'] + const pinnedStatusIds = [...pinnedStatusIdSet1, ...pinnedStatusIdSet2] + const statusIds = [...pinnedStatusIdSet1, 'UNPINNED1', ...pinnedStatusIdSet2] + const statuses = mockStatuses(statusIds) + expect(getExcludedStatusIdsByPinning(statuses, pinnedStatusIds)).to.eql(pinnedStatusIdSet1) + }) + }) +}) diff --git a/test/unit/specs/components/user_profile.spec.js b/test/unit/specs/components/user_profile.spec.js index 41fd9cd0..6de9491a 100644 --- a/test/unit/specs/components/user_profile.spec.js +++ b/test/unit/specs/components/user_profile.spec.js @@ -12,9 +12,13 @@ const mutations = { setError: () => {} } +const actions = { + fetchUser: () => {}, + fetchUserByScreenName: () => {} +} + const testGetters = { - userByName: state => getters.userByName(state.users), - userById: state => getters.userById(state.users) + findUser: state => getters.findUser(state.users) } const localUser = { @@ -31,9 +35,11 @@ const extUser = { const externalProfileStore = new Vuex.Store({ mutations, + actions, getters: testGetters, state: { api: { + fetchers: {}, backendInteractor: backendInteractorService('') }, interface: { @@ -89,7 +95,7 @@ const externalProfileStore = new Vuex.Store({ currentUser: { credentials: '' }, - usersObject: [extUser], + usersObject: { 100: extUser }, users: [extUser] } } @@ -97,9 +103,11 @@ const externalProfileStore = new Vuex.Store({ const localProfileStore = new Vuex.Store({ mutations, + actions, getters: testGetters, state: { api: { + fetchers: {}, backendInteractor: backendInteractorService('') }, interface: { @@ -155,7 +163,7 @@ const localProfileStore = new Vuex.Store({ currentUser: { credentials: '' }, - usersObject: [localUser], + usersObject: { 100: localUser, 'testuser': localUser }, users: [localUser] } } diff --git a/test/unit/specs/modules/statuses.spec.js b/test/unit/specs/modules/statuses.spec.js index 0bbcb25a..f794997b 100644 --- a/test/unit/specs/modules/statuses.spec.js +++ b/test/unit/specs/modules/statuses.spec.js @@ -1,10 +1,10 @@ import { defaultState, mutations, prepareStatus } from '../../../../src/modules/statuses.js' // eslint-disable-next-line camelcase -const makeMockStatus = ({id, text, type = 'status'}) => { +const makeMockStatus = ({ id, text, type = 'status' }) => { return { id, - user: {id: '0'}, + user: { id: '0' }, name: 'status', text: text || `Text number ${id}`, fave_num: 0, @@ -17,7 +17,7 @@ const makeMockStatus = ({id, text, type = 'status'}) => { describe('Statuses module', () => { describe('prepareStatus', () => { it('sets deleted flag to false', () => { - const aStatus = makeMockStatus({id: '1', text: 'Hello oniichan'}) + const aStatus = makeMockStatus({ id: '1', text: 'Hello oniichan' }) expect(prepareStatus(aStatus).deleted).to.eq(false) }) }) @@ -25,7 +25,7 @@ describe('Statuses module', () => { describe('addNewStatuses', () => { it('adds the status to allStatuses and to the given timeline', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) + const status = makeMockStatus({ id: '1' }) mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) @@ -37,7 +37,7 @@ describe('Statuses module', () => { it('counts the status as new if it has not been seen on this timeline', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) + const status = makeMockStatus({ id: '1' }) mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) mutations.addNewStatuses(state, { statuses: [status], timeline: 'friends' }) @@ -55,7 +55,7 @@ describe('Statuses module', () => { it('add the statuses to allStatuses if no timeline is given', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) + const status = makeMockStatus({ id: '1' }) mutations.addNewStatuses(state, { statuses: [status] }) @@ -67,7 +67,7 @@ describe('Statuses module', () => { it('adds the status to allStatuses and to the given timeline, directly visible', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) + const status = makeMockStatus({ id: '1' }) mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) @@ -79,10 +79,10 @@ describe('Statuses module', () => { it('removes statuses by tag on deletion', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) - const otherStatus = makeMockStatus({id: '3'}) + const status = makeMockStatus({ id: '1' }) + const otherStatus = makeMockStatus({ id: '3' }) status.uri = 'xxx' - const deletion = makeMockStatus({id: '2', type: 'deletion'}) + const deletion = makeMockStatus({ id: '2', type: 'deletion' }) deletion.text = 'Dolus deleted notice {{tag:gs.smuglo.li,2016-11-18:noticeId=1038007:objectType=note}}.' deletion.uri = 'xxx' @@ -97,8 +97,8 @@ describe('Statuses module', () => { it('does not update the maxId when the noIdUpdate flag is set', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) - const secondStatus = makeMockStatus({id: '2'}) + const status = makeMockStatus({ id: '1' }) + const secondStatus = makeMockStatus({ id: '2' }) mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) expect(state.timelines.public.maxId).to.eql('1') @@ -111,10 +111,10 @@ describe('Statuses module', () => { it('keeps a descending by id order in timeline.visibleStatuses and timeline.statuses', () => { const state = defaultState() - const nonVisibleStatus = makeMockStatus({id: '1'}) - const status = makeMockStatus({id: '3'}) - const statusTwo = makeMockStatus({id: '2'}) - const statusThree = makeMockStatus({id: '4'}) + const nonVisibleStatus = makeMockStatus({ id: '1' }) + const status = makeMockStatus({ id: '3' }) + const statusTwo = makeMockStatus({ id: '2' }) + const statusThree = makeMockStatus({ id: '4' }) mutations.addNewStatuses(state, { statuses: [nonVisibleStatus], showImmediately: false, timeline: 'public' }) @@ -131,9 +131,9 @@ describe('Statuses module', () => { it('splits retweets from their status and links them', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) - const retweet = makeMockStatus({id: '2', type: 'retweet'}) - const modStatus = makeMockStatus({id: '1', text: 'something else'}) + const status = makeMockStatus({ id: '1' }) + const retweet = makeMockStatus({ id: '2', type: 'retweet' }) + const modStatus = makeMockStatus({ id: '1', text: 'something else' }) retweet.retweeted_status = status @@ -156,8 +156,8 @@ describe('Statuses module', () => { it('replaces existing statuses with the same id', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) - const modStatus = makeMockStatus({id: '1', text: 'something else'}) + const status = makeMockStatus({ id: '1' }) + const modStatus = makeMockStatus({ id: '1', text: 'something else' }) // Add original status mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) @@ -173,9 +173,9 @@ describe('Statuses module', () => { it('replaces existing statuses with the same id, coming from a retweet', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) - const modStatus = makeMockStatus({id: '1', text: 'something else'}) - const retweet = makeMockStatus({id: '2', type: 'retweet'}) + const status = makeMockStatus({ id: '1' }) + const modStatus = makeMockStatus({ id: '1', text: 'something else' }) + const retweet = makeMockStatus({ id: '2', type: 'retweet' }) retweet.retweeted_status = modStatus // Add original status @@ -194,7 +194,7 @@ describe('Statuses module', () => { it('handles favorite actions', () => { const state = defaultState() - const status = makeMockStatus({id: '1'}) + const status = makeMockStatus({ id: '1' }) const favorite = { id: '2', @@ -258,11 +258,11 @@ describe('Statuses module', () => { }) describe('clearTimeline', () => { - it('keeps userId when clearing user timeline', () => { + it('keeps userId when clearing user timeline when excludeUserId param is true', () => { const state = defaultState() state.timelines.user.userId = 123 - mutations.clearTimeline(state, { timeline: 'user' }) + mutations.clearTimeline(state, { timeline: 'user', excludeUserId: true }) expect(state.timelines.user.userId).to.eql(123) }) @@ -272,14 +272,14 @@ describe('Statuses module', () => { it('removes a notification when the notice gets removed', () => { const user = { id: '1' } const state = defaultState() - const status = makeMockStatus({id: '1'}) - const otherStatus = makeMockStatus({id: '3'}) - const mentionedStatus = makeMockStatus({id: '2'}) + const status = makeMockStatus({ id: '1' }) + const otherStatus = makeMockStatus({ id: '3' }) + const mentionedStatus = makeMockStatus({ id: '2' }) mentionedStatus.attentions = [user] mentionedStatus.uri = 'xxx' otherStatus.attentions = [user] - const deletion = makeMockStatus({id: '4', type: 'deletion'}) + const deletion = makeMockStatus({ id: '4', type: 'deletion' }) deletion.text = 'Dolus deleted notice {{tag:gs.smuglo.li,2016-11-18:noticeId=1038007:objectType=note}}.' deletion.uri = 'xxx' diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js index 4d49ee24..eeb7afef 100644 --- a/test/unit/specs/modules/users.spec.js +++ b/test/unit/specs/modules/users.spec.js @@ -24,50 +24,41 @@ describe('The users module', () => { const user = { id: '1', name: 'Guy' } mutations.addNewUsers(state, [user]) - mutations.setMuted(state, {user, muted: true}) + mutations.setMuted(state, { user, muted: true }) expect(user.muted).to.eql(true) - mutations.setMuted(state, {user, muted: false}) + mutations.setMuted(state, { user, muted: false }) expect(user.muted).to.eql(false) }) }) - 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.userByName(state)(name)).to.eql(expected) + 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.userByName(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' } - expect(getters.userById(state)(id)).to.eql(expected) + expect(getters.findUser(state)(id)).to.eql(expected) }) }) }) diff --git a/test/unit/specs/services/date_utils/date_utils.spec.js b/test/unit/specs/services/date_utils/date_utils.spec.js new file mode 100644 index 00000000..2d61dbac --- /dev/null +++ b/test/unit/specs/services/date_utils/date_utils.spec.js @@ -0,0 +1,40 @@ +import * as DateUtils from 'src/services/date_utils/date_utils.js' + +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' }) + }) + + it('rounds down for past', () => { + const time = Date.now() - 1.8 * DateUtils.HOUR + expect(DateUtils.relativeTime(time)).to.eql({ num: 1, key: 'time.hour' }) + }) + + it('rounds up for future', () => { + const time = Date.now() + 1.8 * DateUtils.HOUR + expect(DateUtils.relativeTime(time)).to.eql({ num: 2, key: 'time.hours' }) + }) + + it('uses plural when necessary', () => { + const time = Date.now() - 3.8 * DateUtils.WEEK + expect(DateUtils.relativeTime(time)).to.eql({ num: 3, key: 'time.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.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.years_short' }) + }) + }) +}) 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..49f378e2 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' @@ -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) } @@ -143,11 +146,22 @@ const makeMockNotificationQvitter = (overrides = {}) => { }, overrides) } -parseNotification -parseUser -parseStatus -makeMockStatusQvitter -makeMockUserQvitter +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]) + ] +} describe('API Entities normalizer', () => { describe('parseStatus', () => { @@ -186,15 +200,15 @@ describe('API Entities normalizer', () => { }) 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 safe = makeMockStatusQvitter({ id: '1', text: 'Hello oniichan' }) + 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) }) @@ -218,6 +232,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('<img') + }) + + it('adds emojis to subject line', () => { + const post = makeMockStatusMasto({ emojis: makeMockEmojiMasto(), spoiler_text: 'CW: 300 IQ :thinking:' }) + + const parsedPost = parseStatus(post) + + expect(parsedPost).to.have.property('summary_html').that.contains('<img') + }) }) }) @@ -230,6 +260,31 @@ describe('API Entities normalizer', () => { 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('<img') + }) + + it('adds emojis to user bio', () => { + 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('<img') + }) + + 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 } }) + + expect(parseUser(user)).to.have.property('hide_followers', true) + expect(parseUser(user)).to.have.property('hide_follows', false) + expect(parseUser(user)).to.have.property('hide_followers_count', false) + expect(parseUser(user)).to.have.property('hide_follows_count', true) + }) }) // We currently use QvitterAPI notifications only, and especially due to MastoAPI lacking is_seen, support for MastoAPI @@ -267,4 +322,39 @@ describe('API Entities normalizer', () => { expect(parseNotification(notif)).to.have.deep.property('from_profile.id', 'spurdo') }) }) + + describe('MastoAPI emoji adder', () => { + const emojis = makeMockEmojiMasto() + const imageHtml = '<img src="https://example.com/image.png" alt="image" title="image" class="emoji" />' + .replace(/"/g, '\'') + const thinkHtml = '<img src="https://example.com/think.png" alt="thinking" title="thinking" class="emoji" />' + .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') + }) + + it('Doesn\'t blow up on regex special characters', () => { + const emojis = makeMockEmojiMasto([{ + shortcode: 'c++' + }, { + shortcode: '[a-z] {|}*' + }]) + const result = addEmojis('This post has :c++: emoji and :[a-z] {|}*: emoji', emojis) + expect(result).to.include('title=\'c++\'') + expect(result).to.include('title=\'[a-z] {|}*\'') + }) + }) }) diff --git a/test/unit/specs/services/file_size_format/file_size_format.spec.js b/test/unit/specs/services/file_size_format/file_size_format.spec.js index 0a5a82b7..e02ac379 100644 --- a/test/unit/specs/services/file_size_format/file_size_format.spec.js +++ b/test/unit/specs/services/file_size_format/file_size_format.spec.js @@ -1,34 +1,34 @@ - import fileSizeFormatService from '../../../../../src/services/file_size_format/file_size_format.js' - describe('fileSizeFormat', () => { - it('Formats file size', () => { - const values = [1, 1024, 1048576, 1073741824, 1099511627776] - const expected = [ - { - num: 1, - unit: 'B' - }, - { - num: 1, - unit: 'KiB' - }, - { - num: 1, - unit: 'MiB' - }, - { - num: 1, - unit: 'GiB' - }, - { - num: 1, - unit: 'TiB' - } - ] +import fileSizeFormatService from '../../../../../src/services/file_size_format/file_size_format.js' +describe('fileSizeFormat', () => { + it('Formats file size', () => { + const values = [1, 1024, 1048576, 1073741824, 1099511627776] + const expected = [ + { + num: 1, + unit: 'B' + }, + { + num: 1, + unit: 'KiB' + }, + { + num: 1, + unit: 'MiB' + }, + { + num: 1, + unit: 'GiB' + }, + { + num: 1, + unit: 'TiB' + } + ] - var res = [] - for (var value in values) { - res.push(fileSizeFormatService.fileSizeFormat(values[value])) - } - expect(res).to.eql(expected) - }) - }) + var res = [] + for (var value in values) { + res.push(fileSizeFormatService.fileSizeFormat(values[value])) + } + expect(res).to.eql(expected) + }) +}) 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..a91f95db --- /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('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) + }) + }) +}) 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' } ] diff --git a/test/unit/specs/services/status_parser/status_parses.spec.js b/test/unit/specs/services/status_parser/status_parses.spec.js index 65808d84..7afd5042 100644 --- a/test/unit/specs/services/status_parser/status_parses.spec.js +++ b/test/unit/specs/services/status_parser/status_parses.spec.js @@ -1,7 +1,7 @@ -const example = '<div class="status-content">@<a href="https://sealion.club/user/4" class="h-card mention" title="dewoo">dwmatiz</a> <a href="https://social.heldscal.la/file/3deb764ada10ce64a61b7a070b75dac45f86d2d5bf213bf18873da71d8714d86.png" title="https://social.heldscal.la/file/3deb764ada10ce64a61b7a070b75dac45f86d2d5bf213bf18873da71d8714d86.png" class="attachment" id="attachment-159853" rel="nofollow external">https://social.heldscal.la/attachment/159853</a></div>' - import { removeAttachmentLinks } from '../../../../../src/services/status_parser/status_parser.js' +const example = '<div class="status-content">@<a href="https://sealion.club/user/4" class="h-card mention" title="dewoo">dwmatiz</a> <a href="https://social.heldscal.la/file/3deb764ada10ce64a61b7a070b75dac45f86d2d5bf213bf18873da71d8714d86.png" title="https://social.heldscal.la/file/3deb764ada10ce64a61b7a070b75dac45f86d2d5bf213bf18873da71d8714d86.png" class="attachment" id="attachment-159853" rel="nofollow external">https://social.heldscal.la/attachment/159853</a></div>' + describe('statusParser.removeAttachmentLinks', () => { const exampleWithoutAttachmentLinks = '<div class="status-content">@<a href="https://sealion.club/user/4" class="h-card mention" title="dewoo">dwmatiz</a> </div>' diff --git a/test/unit/specs/services/version/version.service.spec.js b/test/unit/specs/services/version/version.service.spec.js new file mode 100644 index 00000000..519145ee --- /dev/null +++ b/test/unit/specs/services/version/version.service.spec.js @@ -0,0 +1,11 @@ +import { extractCommit } from 'src/services/version/version.service.js' + +describe('extractCommit', () => { + it('return short commit hash following "-g" characters', () => { + expect(extractCommit('1.0.0-45-g5e7aeebc')).to.eql('5e7aeebc') + }) + + it('return short commit hash without branch name', () => { + expect(extractCommit('1.0.0-45-g5e7aeebc-branch')).to.eql('5e7aeebc') + }) +}) |
