about summary refs log tree commit diff
path: root/spec
diff options
context:
space:
mode:
authorEugen Rochko <eugen@zeonfederated.com>2017-09-19 02:42:40 +0200
committerGitHub <noreply@github.com>2017-09-19 02:42:40 +0200
commit81cec35dbf1b348d23363559e3f4e6b1ec3415c5 (patch)
treed449c3c19a8147bd1bc44fc703a1fccb9b9b894d /spec
parentc155d843f4d523d52ce4ce67491578385c06fd1b (diff)
Custom emoji (#4988)
* Custom emoji

- In OStatus: `<link rel="emoji" name="coolcat" href="http://..." />`
- In ActivityPub: `{ type: "Emoji", name: ":coolcat:", href: "http://..." }`
- In REST API: Status object includes `emojis` array (`shortcode`, `url`)
- Domain blocks with reject media stop emojis
- Emoji file up to 50KB
- Web UI handles custom emojis
- Static pages render custom emojis as `<img />` tags

Side effects:

- Undo #4500 optimization, as I needed to modify it to restore
  shortcode handling in emojify()
- Formatter#plaintext should now make sure stripped out line-breaks
  and paragraphs are replaced with newlines

* Fix emoji at the start not being converted
Diffstat (limited to 'spec')
-rw-r--r--spec/fabricators/custom_emoji_fabricator.rb5
-rw-r--r--spec/fixtures/files/emojo.pngbin0 -> 29814 bytes
-rw-r--r--spec/lib/activitypub/activity/create_spec.rb25
-rw-r--r--spec/lib/formatter_spec.rb78
-rw-r--r--spec/lib/ostatus/atom_serializer_spec.rb16
-rw-r--r--spec/models/custom_emoji_spec.rb25
6 files changed, 147 insertions, 2 deletions
diff --git a/spec/fabricators/custom_emoji_fabricator.rb b/spec/fabricators/custom_emoji_fabricator.rb
new file mode 100644
index 000000000..18a7d23dc
--- /dev/null
+++ b/spec/fabricators/custom_emoji_fabricator.rb
@@ -0,0 +1,5 @@
+Fabricator(:custom_emoji) do
+  shortcode 'coolcat'
+  domain    nil
+  image     { File.open(Rails.root.join('spec', 'fixtures', 'files', 'emojo.png')) }
+end
diff --git a/spec/fixtures/files/emojo.png b/spec/fixtures/files/emojo.png
new file mode 100644
index 000000000..cb5993499
--- /dev/null
+++ b/spec/fixtures/files/emojo.png
Binary files differdiff --git a/spec/lib/activitypub/activity/create_spec.rb b/spec/lib/activitypub/activity/create_spec.rb
index fcb044ebc..1a9520f04 100644
--- a/spec/lib/activitypub/activity/create_spec.rb
+++ b/spec/lib/activitypub/activity/create_spec.rb
@@ -17,6 +17,7 @@ RSpec.describe ActivityPub::Activity::Create do
 
   before do
     stub_request(:get, 'http://example.com/attachment.png').to_return(request_fixture('avatar.txt'))
+    stub_request(:get, 'http://example.com/emoji.png').to_return(body: attachment_fixture('emojo.png'))
   end
 
   describe '#perform' do
@@ -217,5 +218,29 @@ RSpec.describe ActivityPub::Activity::Create do
         expect(status.tags.map(&:name)).to include('test')
       end
     end
+
+    context 'with emojis' do
+      let(:object_json) do
+        {
+          id: 'bar',
+          type: 'Note',
+          content: 'Lorem ipsum :tinking:',
+          tag: [
+            {
+              type: 'Emoji',
+              href: 'http://example.com/emoji.png',
+              name: 'tinking',
+            },
+          ],
+        }
+      end
+
+      it 'creates status' do
+        status = sender.statuses.first
+
+        expect(status).to_not be_nil
+        expect(status.emojis.map(&:shortcode)).to include('tinking')
+      end
+    end
   end
 end
diff --git a/spec/lib/formatter_spec.rb b/spec/lib/formatter_spec.rb
index b714b317a..71b6b78d2 100644
--- a/spec/lib/formatter_spec.rb
+++ b/spec/lib/formatter_spec.rb
@@ -223,6 +223,45 @@ RSpec.describe Formatter do
 
         include_examples 'encode and link URLs'
       end
+
+      context 'with custom_emojify option' do
+        let!(:emoji) { Fabricate(:custom_emoji) }
+        let(:status) { Fabricate(:status, account: local_account, text: text) }
+
+        subject { Formatter.instance.format(status, custom_emojify: true) }
+
+        context 'with emoji at the start' do
+          let(:text) { ':coolcat: Beep boop' }
+
+          it 'converts shortcode to image tag' do
+            is_expected.to match(/<p><img draggable="false" class="emojione" alt=":coolcat:"/)
+          end
+        end
+
+        context 'with emoji in the middle' do
+          let(:text) { 'Beep :coolcat: boop' }
+
+          it 'converts shortcode to image tag' do
+            is_expected.to match(/Beep <img draggable="false" class="emojione" alt=":coolcat:"/)
+          end
+        end
+
+        context 'with concatenated emoji' do
+          let(:text) { ':coolcat::coolcat:' }
+
+          it 'does not touch the shortcodes' do
+            is_expected.to match(/:coolcat::coolcat:/)
+          end
+        end
+
+        context 'with emoji at the end' do
+          let(:text) { 'Beep boop :coolcat:' }
+
+          it 'converts shortcode to image tag' do
+            is_expected.to match(/boop <img draggable="false" class="emojione" alt=":coolcat:"/)
+          end
+        end
+      end
     end
 
     context 'with remote status' do
@@ -231,6 +270,45 @@ RSpec.describe Formatter do
       it 'reformats' do
         is_expected.to eq 'Beep boop'
       end
+
+      context 'with custom_emojify option' do
+        let!(:emoji) { Fabricate(:custom_emoji, domain: remote_account.domain) }
+        let(:status) { Fabricate(:status, account: remote_account, text: text) }
+
+        subject { Formatter.instance.format(status, custom_emojify: true) }
+
+        context 'with emoji at the start' do
+          let(:text) { '<p>:coolcat: Beep boop<br />' }
+
+          it 'converts shortcode to image tag' do
+            is_expected.to match(/<p><img draggable="false" class="emojione" alt=":coolcat:"/)
+          end
+        end
+
+        context 'with emoji in the middle' do
+          let(:text) { '<p>Beep :coolcat: boop</p>' }
+
+          it 'converts shortcode to image tag' do
+            is_expected.to match(/Beep <img draggable="false" class="emojione" alt=":coolcat:"/)
+          end
+        end
+
+        context 'with concatenated emoji' do
+          let(:text) { '<p>:coolcat::coolcat:</p>' }
+
+          it 'does not touch the shortcodes' do
+            is_expected.to match(/<p>:coolcat::coolcat:<\/p>/)
+          end
+        end
+
+        context 'with emoji at the end' do
+          let(:text) { '<p>Beep boop<br />:coolcat:</p>' }
+
+          it 'converts shortcode to image tag' do
+            is_expected.to match(/<br><img draggable="false" class="emojione" alt=":coolcat:"/)
+          end
+        end
+      end
     end
   end
 
diff --git a/spec/lib/ostatus/atom_serializer_spec.rb b/spec/lib/ostatus/atom_serializer_spec.rb
index 0451eceeb..b2480a53b 100644
--- a/spec/lib/ostatus/atom_serializer_spec.rb
+++ b/spec/lib/ostatus/atom_serializer_spec.rb
@@ -97,11 +97,23 @@ RSpec.describe OStatus::AtomSerializer do
 
       mentioned = element.nodes.find do |node|
         node.name == 'link' &&
-        node[:rel] == 'mentioned' &&
-        node['ostatus:object-type'] == TagManager::TYPES[:person]
+          node[:rel] == 'mentioned' &&
+          node['ostatus:object-type'] == TagManager::TYPES[:person]
       end
+
       expect(mentioned[:href]).to eq 'https://cb6e6126.ngrok.io/users/username'
     end
+
+    it 'appends link elements for emojis' do
+      Fabricate(:custom_emoji)
+
+      status  = Fabricate(:status, text: ':coolcat:')
+      element = serialize(status)
+      emoji   = element.nodes.find { |node| node.name == 'link' && node[:rel] == 'emoji' }
+
+      expect(emoji[:name]).to eq 'coolcat'
+      expect(emoji[:href]).to_not be_blank
+    end
   end
 
   describe 'render' do
diff --git a/spec/models/custom_emoji_spec.rb b/spec/models/custom_emoji_spec.rb
new file mode 100644
index 000000000..cb51e9519
--- /dev/null
+++ b/spec/models/custom_emoji_spec.rb
@@ -0,0 +1,25 @@
+require 'rails_helper'
+
+RSpec.describe CustomEmoji, type: :model do
+  describe '.from_text' do
+    let!(:emojo) { Fabricate(:custom_emoji) }
+
+    subject { described_class.from_text(text, nil) }
+
+    context 'with plain text' do
+      let(:text) { 'Hello :coolcat:' }
+
+      it 'returns records used via shortcodes in text' do
+        is_expected.to include(emojo)
+      end
+    end
+
+    context 'with html' do
+      let(:text) { '<p>Hello :coolcat:</p>' }
+
+      it 'returns records used via shortcodes in text' do
+        is_expected.to include(emojo)
+      end
+    end
+  end
+end