diff options
Diffstat (limited to 'spec')
-rw-r--r-- | spec/javascript/.eslintrc.yml | 3 | ||||
-rw-r--r-- | spec/javascript/components/avatar.test.js | 44 | ||||
-rw-r--r-- | spec/javascript/components/avatar_overlay.test.js | 36 | ||||
-rw-r--r-- | spec/javascript/components/button.test.js | 72 | ||||
-rw-r--r-- | spec/javascript/components/display_name.test.js | 18 | ||||
-rw-r--r-- | spec/javascript/components/emoji_index.test.js | 111 | ||||
-rw-r--r-- | spec/javascript/components/emojify.test.js | 61 | ||||
-rw-r--r-- | spec/javascript/components/features/ui/components/column.test.js | 30 | ||||
-rw-r--r-- | spec/javascript/setup.js | 15 | ||||
-rw-r--r-- | spec/lib/feed_manager_spec.rb | 61 |
10 files changed, 47 insertions, 404 deletions
diff --git a/spec/javascript/.eslintrc.yml b/spec/javascript/.eslintrc.yml deleted file mode 100644 index 6db2a46c5..000000000 --- a/spec/javascript/.eslintrc.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -env: - mocha: true diff --git a/spec/javascript/components/avatar.test.js b/spec/javascript/components/avatar.test.js deleted file mode 100644 index 34949f2b5..000000000 --- a/spec/javascript/components/avatar.test.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import Avatar from '../../../app/javascript/mastodon/components/avatar'; - -import { expect } from 'chai'; -import { render } from 'enzyme'; -import { fromJS } from 'immutable'; - -describe('<Avatar />', () => { - const account = fromJS({ - username: 'alice', - acct: 'alice', - display_name: 'Alice', - avatar: '/animated/alice.gif', - avatar_static: '/static/alice.jpg', - }); - - const size = 100; - const animated = render(<Avatar account={account} animate size={size} />); - const still = render(<Avatar account={account} size={size} />); - - // Autoplay - xit('renders a div element with the given src as background', () => { - expect(animated.find('div')).to.have.style('background-image', `url(${account.get('avatar')})`); - }); - - xit('renders a div element of the given size', () => { - ['width', 'height'].map((attr) => { - expect(animated.find('div')).to.have.style(attr, `${size}px`); - }); - }); - - // Still - xit('renders a div element with the given static src as background if not autoplay', () => { - expect(still.find('div')).to.have.style('background-image', `url(${account.get('avatar_static')})`); - }); - - xit('renders a div element of the given size if not autoplay', () => { - ['width', 'height'].map((attr) => { - expect(still.find('div')).to.have.style(attr, `${size}px`); - }); - }); - - // TODO add autoplay test if possible -}); diff --git a/spec/javascript/components/avatar_overlay.test.js b/spec/javascript/components/avatar_overlay.test.js deleted file mode 100644 index fe1d3a012..000000000 --- a/spec/javascript/components/avatar_overlay.test.js +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import AvatarOverlay from '../../../app/javascript/mastodon/components/avatar_overlay'; - -import { expect } from 'chai'; -import { render } from 'enzyme'; -import { fromJS } from 'immutable'; - -describe('<Avatar />', () => { - const account = fromJS({ - username: 'alice', - acct: 'alice', - display_name: 'Alice', - avatar: '/animated/alice.gif', - avatar_static: '/static/alice.jpg', - }); - - const friend = fromJS({ - username: 'eve', - acct: 'eve@blackhat.lair', - display_name: 'Evelyn', - avatar: '/animated/eve.gif', - avatar_static: '/static/eve.jpg', - }); - - const overlay = render(<AvatarOverlay account={account} friend={friend} />); - - xit('renders account static src as base of overlay avatar', () => { - expect(overlay.find('.account__avatar-overlay-base')) - .to.have.style('background-image', `url(${account.get('avatar_static')})`); - }); - - xit('renders friend static src as overlay of overlay avatar', () => { - expect(overlay.find('.account__avatar-overlay-overlay')) - .to.have.style('background-image', `url(${friend.get('avatar_static')})`); - }); -}); diff --git a/spec/javascript/components/button.test.js b/spec/javascript/components/button.test.js deleted file mode 100644 index d2cd0b4e7..000000000 --- a/spec/javascript/components/button.test.js +++ /dev/null @@ -1,72 +0,0 @@ -import React from 'react'; -import Button from '../../../app/javascript/mastodon/components/button'; - -import { expect } from 'chai'; -import { shallow } from 'enzyme'; -import sinon from 'sinon'; - -describe('<Button />', () => { - xit('renders a button element', () => { - const wrapper = shallow(<Button />); - expect(wrapper).to.match('button'); - }); - - xit('renders the given text', () => { - const text = 'foo'; - const wrapper = shallow(<Button text={text} />); - expect(wrapper.find('button')).to.have.text(text); - }); - - it('handles click events using the given handler', () => { - const handler = sinon.spy(); - const wrapper = shallow(<Button onClick={handler} />); - wrapper.find('button').simulate('click'); - expect(handler.calledOnce).to.equal(true); - }); - - it('does not handle click events if props.disabled given', () => { - const handler = sinon.spy(); - const wrapper = shallow(<Button onClick={handler} disabled />); - wrapper.find('button').simulate('click'); - expect(handler.called).to.equal(false); - }); - - xit('renders a disabled attribute if props.disabled given', () => { - const wrapper = shallow(<Button disabled />); - expect(wrapper.find('button')).to.be.disabled(); - }); - - xit('renders the children', () => { - const children = <p>children</p>; - const wrapper = shallow(<Button>{children}</Button>); - expect(wrapper.find('button')).to.contain(children); - }); - - xit('renders the props.text instead of children', () => { - const text = 'foo'; - const children = <p>children</p>; - const wrapper = shallow(<Button text={text}>{children}</Button>); - expect(wrapper.find('button')).to.have.text(text); - expect(wrapper.find('button')).to.not.contain(children); - }); - - xit('renders style="display: block; width: 100%;" if props.block given', () => { - const wrapper = shallow(<Button block />); - expect(wrapper.find('button')).to.have.className('button--block'); - }); - - xit('renders style="display: inline-block; width: auto;" by default', () => { - const wrapper = shallow(<Button />); - expect(wrapper.find('button')).to.not.have.className('button--block'); - }); - - xit('adds class "button-secondary" if props.secondary given', () => { - const wrapper = shallow(<Button secondary />); - expect(wrapper.find('button')).to.have.className('button-secondary'); - }); - - xit('does not add class "button-secondary" by default', () => { - const wrapper = shallow(<Button />); - expect(wrapper.find('button')).to.not.have.className('button-secondary'); - }); -}); diff --git a/spec/javascript/components/display_name.test.js b/spec/javascript/components/display_name.test.js deleted file mode 100644 index 97a111894..000000000 --- a/spec/javascript/components/display_name.test.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import DisplayName from '../../../app/javascript/mastodon/components/display_name'; - -import { expect } from 'chai'; -import { render } from 'enzyme'; -import { fromJS } from 'immutable'; - -describe('<DisplayName />', () => { - xit('renders display name + account name', () => { - const account = fromJS({ - username: 'bar', - acct: 'bar@baz', - display_name_html: '<p>Foo</p>', - }); - const wrapper = render(<DisplayName account={account} />); - expect(wrapper).to.have.text('Foo @bar@baz'); - }); -}); diff --git a/spec/javascript/components/emoji_index.test.js b/spec/javascript/components/emoji_index.test.js deleted file mode 100644 index cdb50cb8c..000000000 --- a/spec/javascript/components/emoji_index.test.js +++ /dev/null @@ -1,111 +0,0 @@ -import { expect } from 'chai'; -import { search } from '../../../app/javascript/mastodon/features/emoji/emoji_mart_search_light'; -import { emojiIndex } from 'emoji-mart'; -import { pick } from 'lodash'; - -const trimEmojis = emoji => pick(emoji, ['id', 'unified', 'native', 'custom']); - -// hack to fix https://github.com/chaijs/type-detect/issues/98 -// see: https://github.com/chaijs/type-detect/issues/98#issuecomment-325010785 -import jsdom from 'jsdom'; -global.window = new jsdom.JSDOM().window; -global.document = window.document; -global.HTMLElement = window.HTMLElement; - -describe('emoji_index', () => { - - it('should give same result for emoji_index_light and emoji-mart', () => { - let expected = [{ - id: 'pineapple', - unified: '1f34d', - native: '๐', - }]; - expect(search('pineapple').map(trimEmojis)).to.deep.equal(expected); - expect(emojiIndex.search('pineapple').map(trimEmojis)).to.deep.equal(expected); - }); - - it('orders search results correctly', () => { - let expected = [{ - id: 'apple', - unified: '1f34e', - native: '๐', - }, { - id: 'pineapple', - unified: '1f34d', - native: '๐', - }, { - id: 'green_apple', - unified: '1f34f', - native: '๐', - }, { - id: 'iphone', - unified: '1f4f1', - native: '๐ฑ', - }]; - expect(search('apple').map(trimEmojis)).to.deep.equal(expected); - expect(emojiIndex.search('apple').map(trimEmojis)).to.deep.equal(expected); - }); - - it('handles custom emoji', () => { - let custom = [{ - id: 'mastodon', - name: 'mastodon', - short_names: ['mastodon'], - text: '', - emoticons: [], - keywords: ['mastodon'], - imageUrl: 'http://example.com', - custom: true, - }]; - search('', { custom }); - emojiIndex.search('', { custom }); - let expected = [ { id: 'mastodon', custom: true } ]; - expect(search('masto').map(trimEmojis)).to.deep.equal(expected); - expect(emojiIndex.search('masto').map(trimEmojis)).to.deep.equal(expected); - }); - - it('should filter only emojis we care about, exclude pineapple', () => { - let emojisToShowFilter = (unified) => unified !== '1F34D'; - expect(search('apple', { emojisToShowFilter }).map((obj) => obj.id)) - .not.to.contain('pineapple'); - expect(emojiIndex.search('apple', { emojisToShowFilter }).map((obj) => obj.id)) - .not.to.contain('pineapple'); - }); - - it('can include/exclude categories', () => { - expect(search('flag', { include: ['people'] })) - .to.deep.equal([]); - expect(emojiIndex.search('flag', { include: ['people'] })) - .to.deep.equal([]); - }); - - it('does an emoji whose unified name is irregular', () => { - let expected = [{ - 'id': 'water_polo', - 'unified': '1f93d', - 'native': '๐คฝ', - }, { - 'id': 'man-playing-water-polo', - 'unified': '1f93d-200d-2642-fe0f', - 'native': '๐คฝโโ๏ธ', - }, { - 'id': 'woman-playing-water-polo', - 'unified': '1f93d-200d-2640-fe0f', - 'native': '๐คฝโโ๏ธ', - }]; - expect(search('polo').map(trimEmojis)).to.deep.equal(expected); - expect(emojiIndex.search('polo').map(trimEmojis)).to.deep.equal(expected); - }); - - it('can search for thinking_face', () => { - let expected = [ { id: 'thinking_face', unified: '1f914', native: '๐ค' } ]; - expect(search('thinking_fac').map(trimEmojis)).to.deep.equal(expected); - expect(emojiIndex.search('thinking_fac').map(trimEmojis)).to.deep.equal(expected); - }); - - it('can search for woman-facepalming', () => { - let expected = [ { id: 'woman-facepalming', unified: '1f926-200d-2640-fe0f', native: '๐คฆโโ๏ธ' } ]; - expect(search('woman-facep').map(trimEmojis)).to.deep.equal(expected); - expect(emojiIndex.search('woman-facep').map(trimEmojis)).deep.equal(expected); - }); -}); diff --git a/spec/javascript/components/emojify.test.js b/spec/javascript/components/emojify.test.js deleted file mode 100644 index 3105c8e3f..000000000 --- a/spec/javascript/components/emojify.test.js +++ /dev/null @@ -1,61 +0,0 @@ -import { expect } from 'chai'; -import emojify from '../../../app/javascript/mastodon/features/emoji/emoji'; - -describe('emojify', () => { - it('ignores unknown shortcodes', () => { - expect(emojify(':foobarbazfake:')).to.equal(':foobarbazfake:'); - }); - - it('ignores shortcodes inside of tags', () => { - expect(emojify('<p data-foo=":smile:"></p>')).to.equal('<p data-foo=":smile:"></p>'); - }); - - it('works with unclosed tags', () => { - expect(emojify('hello>')).to.equal('hello>'); - expect(emojify('<hello')).to.equal('<hello'); - }); - - it('works with unclosed shortcodes', () => { - expect(emojify('smile:')).to.equal('smile:'); - expect(emojify(':smile')).to.equal(':smile'); - }); - - it('does unicode', () => { - expect(emojify('\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66')).to.equal( - '<img draggable="false" class="emojione" alt="๐ฉโ๐ฉโ๐ฆโ๐ฆ" title=":woman-woman-boy-boy:" src="/emoji/1f469-200d-1f469-200d-1f466-200d-1f466.svg" />'); - expect(emojify('๐จโ๐ฉโ๐งโ๐ง')).to.equal( - '<img draggable="false" class="emojione" alt="๐จโ๐ฉโ๐งโ๐ง" title=":man-woman-girl-girl:" src="/emoji/1f468-200d-1f469-200d-1f467-200d-1f467.svg" />'); - expect(emojify('๐ฉโ๐ฉโ๐ฆ')).to.equal('<img draggable="false" class="emojione" alt="๐ฉโ๐ฉโ๐ฆ" title=":woman-woman-boy:" src="/emoji/1f469-200d-1f469-200d-1f466.svg" />'); - expect(emojify('\u2757')).to.equal( - '<img draggable="false" class="emojione" alt="โ" title=":exclamation:" src="/emoji/2757.svg" />'); - }); - - it('does multiple unicode', () => { - expect(emojify('\u2757 #\uFE0F\u20E3')).to.equal( - '<img draggable="false" class="emojione" alt="โ" title=":exclamation:" src="/emoji/2757.svg" /> <img draggable="false" class="emojione" alt="#๏ธโฃ" title=":hash:" src="/emoji/23-20e3.svg" />'); - expect(emojify('\u2757#\uFE0F\u20E3')).to.equal( - '<img draggable="false" class="emojione" alt="โ" title=":exclamation:" src="/emoji/2757.svg" /><img draggable="false" class="emojione" alt="#๏ธโฃ" title=":hash:" src="/emoji/23-20e3.svg" />'); - expect(emojify('\u2757 #\uFE0F\u20E3 \u2757')).to.equal( - '<img draggable="false" class="emojione" alt="โ" title=":exclamation:" src="/emoji/2757.svg" /> <img draggable="false" class="emojione" alt="#๏ธโฃ" title=":hash:" src="/emoji/23-20e3.svg" /> <img draggable="false" class="emojione" alt="โ" title=":exclamation:" src="/emoji/2757.svg" />'); - expect(emojify('foo \u2757 #\uFE0F\u20E3 bar')).to.equal( - 'foo <img draggable="false" class="emojione" alt="โ" title=":exclamation:" src="/emoji/2757.svg" /> <img draggable="false" class="emojione" alt="#๏ธโฃ" title=":hash:" src="/emoji/23-20e3.svg" /> bar'); - }); - - it('ignores unicode inside of tags', () => { - expect(emojify('<p data-foo="\uD83D\uDC69\uD83D\uDC69\uD83D\uDC66"></p>')).to.equal('<p data-foo="\uD83D\uDC69\uD83D\uDC69\uD83D\uDC66"></p>'); - }); - - it('does multiple emoji properly (issue 5188)', () => { - expect(emojify('๐๐๐')).to.equal('<img draggable="false" class="emojione" alt="๐" title=":ok_hand:" src="/emoji/1f44c.svg" /><img draggable="false" class="emojione" alt="๐" title=":rainbow:" src="/emoji/1f308.svg" /><img draggable="false" class="emojione" alt="๐" title=":two_hearts:" src="/emoji/1f495.svg" />'); - expect(emojify('๐ ๐ ๐')).to.equal('<img draggable="false" class="emojione" alt="๐" title=":ok_hand:" src="/emoji/1f44c.svg" /> <img draggable="false" class="emojione" alt="๐" title=":rainbow:" src="/emoji/1f308.svg" /> <img draggable="false" class="emojione" alt="๐" title=":two_hearts:" src="/emoji/1f495.svg" />'); - }); - - it('does an emoji that has no shortcode', () => { - expect(emojify('๐๏ธ')).to.equal('<img draggable="false" class="emojione" alt="๐๏ธ" title="" src="/emoji/1f549.svg" />'); - }); - - it('does an emoji whose filename is irregular', () => { - expect(emojify('โ๏ธ')).to.equal('<img draggable="false" class="emojione" alt="โ๏ธ" title=":arrow_lower_left:" src="/emoji/2199.svg" />'); - }); - -}); diff --git a/spec/javascript/components/features/ui/components/column.test.js b/spec/javascript/components/features/ui/components/column.test.js deleted file mode 100644 index 4491d6e19..000000000 --- a/spec/javascript/components/features/ui/components/column.test.js +++ /dev/null @@ -1,30 +0,0 @@ -import { expect } from 'chai'; -import { mount } from 'enzyme'; -import sinon from 'sinon'; -import React from 'react'; -import Column from '../../../../../../app/javascript/mastodon/features/ui/components/column'; -import ColumnHeader from '../../../../../../app/javascript/mastodon/features/ui/components/column_header'; - -describe('<Column />', () => { - describe('<ColumnHeader /> click handler', () => { - beforeEach(() => { - global.requestAnimationFrame = sinon.spy(); - }); - - it('runs the scroll animation if the column contains scrollable content', () => { - const wrapper = mount( - <Column heading='notifications'> - <div className='scrollable' /> - </Column> - ); - wrapper.find(ColumnHeader).simulate('click'); - expect(global.requestAnimationFrame.called).to.equal(true); - }); - - it('does not try to scroll if there is no scrollable content', () => { - const wrapper = mount(<Column heading='notifications' />); - wrapper.find(ColumnHeader).simulate('click'); - expect(global.requestAnimationFrame.called).to.equal(false); - }); - }); -}); diff --git a/spec/javascript/setup.js b/spec/javascript/setup.js deleted file mode 100644 index ab8a36b95..000000000 --- a/spec/javascript/setup.js +++ /dev/null @@ -1,15 +0,0 @@ -import { JSDOM } from 'jsdom'; -import Enzyme from 'enzyme'; -import Adapter from 'enzyme-adapter-react-16'; - -Enzyme.configure({ adapter: new Adapter() }); - -const { window } = new JSDOM('', { - userAgent: 'node.js', -}); - -Object.keys(window).forEach(property => { - if (typeof global[property] === 'undefined') { - global[property] = window[property]; - } -}); diff --git a/spec/lib/feed_manager_spec.rb b/spec/lib/feed_manager_spec.rb index 923894ccb..454c3afec 100644 --- a/spec/lib/feed_manager_spec.rb +++ b/spec/lib/feed_manager_spec.rb @@ -231,33 +231,66 @@ RSpec.describe FeedManager do end describe '#unpush' do - it 'leaves a reblogged status when deleting the reblog' do - account = Fabricate(:account) + let(:receiver) { Fabricate(:account) } + + it 'leaves a reblogged status if original was on feed' do reblogged = Fabricate(:status) - status = Fabricate(:status, reblog: reblogged) + status = Fabricate(:status, reblog: reblogged) - FeedManager.instance.push('type', account, status) + FeedManager.instance.push('type', receiver, reblogged) + FeedManager::REBLOG_FALLOFF.times { FeedManager.instance.push('type', receiver, Fabricate(:status)) } + FeedManager.instance.push('type', receiver, status) + + # The reblogging status should show up under normal conditions. + expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to include(status.id.to_s) + + FeedManager.instance.unpush('type', receiver, status) + + # Restore original status + expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to_not include(status.id.to_s) + expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to include(reblogged.id.to_s) + end + + it 'removes a reblogged status if it was only reblogged once' do + reblogged = Fabricate(:status) + status = Fabricate(:status, reblog: reblogged) + + FeedManager.instance.push('type', receiver, status) # The reblogging status should show up under normal conditions. - expect(Redis.current.zrange("feed:type:#{account.id}", 0, -1)).to eq [status.id.to_s] + expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to eq [status.id.to_s] - FeedManager.instance.unpush('type', account, status) + FeedManager.instance.unpush('type', receiver, status) - # Because we couldn't tell if the status showed up any other way, - # we had to stick the reblogged status in by itself. - expect(Redis.current.zrange("feed:type:#{account.id}", 0, -1)).to eq [reblogged.id.to_s] + expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to be_empty + end + + it 'leaves a reblogged status if another reblog was in feed' do + reblogged = Fabricate(:status) + status = Fabricate(:status, reblog: reblogged) + another_status = Fabricate(:status, reblog: reblogged) + + FeedManager.instance.push('type', receiver, status) + FeedManager.instance.push('type', receiver, another_status) + + # The reblogging status should show up under normal conditions. + expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to eq [status.id.to_s] + + FeedManager.instance.unpush('type', receiver, status) + + expect(Redis.current.zrange("feed:type:#{receiver.id}", 0, -1)).to eq [another_status.id.to_s] end it 'sends push updates' do - account = Fabricate(:account) - status = Fabricate(:status) - FeedManager.instance.push('type', account, status) + status = Fabricate(:status) + + FeedManager.instance.push('type', receiver, status) allow(Redis.current).to receive_messages(publish: nil) - FeedManager.instance.unpush('type', account, status) + FeedManager.instance.unpush('type', receiver, status) deletion = Oj.dump(event: :delete, payload: status.id.to_s) - expect(Redis.current).to have_received(:publish).with("timeline:#{account.id}", deletion) + expect(Redis.current).to have_received(:publish).with("timeline:#{receiver.id}", deletion) end end end |