Merge pull request #5073 from Zauberstuhl/xmpp_chat_feature

[Feature] XMPP javascript client plus ruby (vines) server
This commit is contained in:
Jonne Haß 2014-11-15 16:59:37 +01:00
commit 7f51d8710e
34 changed files with 471 additions and 15 deletions

View file

@ -1,2 +1,2 @@
port: 3000
formation: web=1,sidekiq=0
formation: xmpp=0,web=1,sidekiq=0

4
.gitignore vendored
View file

@ -1,3 +1,7 @@
# xmpp certificates, keys and user data
config/vines/*.crt
config/vines/*.key
#trademark sillyness
app/views/home/_show.*
app/views/terms/terms.*

View file

@ -32,6 +32,9 @@ series and run our comphrensive testsuite against it.
## Change in defaults.yml
The default for including jQuery from a CDN has changed. If you want to continue to include it from a CDN, please explicitly set the `jquery_cdn` setting to `true` in diaspora.yml.
## Experimental chat feature
This release adds experimental integration with XMPP for realtime chat. Please see [our wiki](https://wiki.diasporafoundation.org/Vines) for further informations.
## Change in statistics.json schema
The way services are shown in the `statistics.json` route is changing. The keys relating to showing whether services are enabled or not are moving to their own container as `"services": {....}`, instead of having them all in the root level of the json.

View file

@ -22,6 +22,7 @@ gem 'json', '1.8.1'
gem 'devise', '3.4.1'
gem 'devise_lastseenable', '0.0.4'
gem 'devise-token_authenticatable', '~> 0.3.0'
# Captcha
@ -126,6 +127,10 @@ gem 'omniauth-twitter', '1.0.1'
gem 'twitter', '4.8.1'
gem 'omniauth-wordpress','0.2.1'
# XMPP chat dependencies
gem 'diaspora-vines', '~> 0.1.25'
gem 'rails-assets-diaspora_jsxc', '~> 0.0.4'
# Tags
gem 'acts-as-taggable-on', '3.4.2'

View file

@ -123,6 +123,8 @@ GEM
responders
thread_safe (~> 0.1)
warden (~> 1.2.3)
devise-token_authenticatable (0.3.0)
devise (~> 3.4.0)
devise_lastseenable (0.0.4)
devise
devise
@ -130,6 +132,13 @@ GEM
rails (>= 3.0.4)
warden
warden
diaspora-vines (0.1.25)
activerecord (~> 4.1.4)
bcrypt (~> 3.1)
em-hiredis (~> 0.3.0)
eventmachine (~> 1.0)
http_parser.rb (~> 0.6)
nokogiri (~> 1.6)
diff-lcs (1.2.5)
eco (1.0.0)
coffee-script
@ -137,11 +146,15 @@ GEM
execjs
eco-source (1.1.0.rc.1)
ejs (1.1.1)
em-hiredis (0.3.0)
eventmachine (~> 1.0)
hiredis (~> 0.5.0)
entypo-rails (2.2.2)
railties (>= 3.1, <= 5)
erubis (2.7.0)
ethon (0.7.1)
ffi (>= 1.3.0)
eventmachine (1.0.3)
excon (0.41.0)
execjs (2.2.2)
factory_girl (4.5.0)
@ -235,7 +248,9 @@ GEM
tilt
hashie (3.3.1)
hike (1.2.3)
hiredis (0.5.2)
http_accept_language (2.0.2)
http_parser.rb (0.6.0)
i18n (0.6.11)
i18n-inflector (2.6.7)
i18n (>= 0.4.1)
@ -370,13 +385,26 @@ GEM
bundler (>= 1.3.0, < 2.0)
railties (= 4.1.7)
sprockets-rails (~> 2.0)
rails-assets-diaspora_jsxc (0.0.4)
rails-assets-jquery (~> 1.11.1)
rails-assets-jquery-colorbox (~> 1.5.14)
rails-assets-jquery-fullscreen (~> 1.1.4)
rails-assets-jquery-ui (~> 1.10.4)
rails-assets-jquery.slimscroll (~> 1.3.3)
rails-assets-jeresig--jquery.hotkeys (0.2.0)
rails-assets-jquery (>= 1.4.2)
rails-assets-jquery (1.11.1)
rails-assets-jquery-colorbox (1.5.14)
rails-assets-jquery (>= 1.3.2)
rails-assets-jquery-fullscreen (1.1.4)
rails-assets-jquery-idletimer (1.0.1)
rails-assets-jquery-placeholder (2.0.8)
rails-assets-jquery-textchange (0.2.3)
rails-assets-jquery
rails-assets-jquery-ui (1.10.4)
rails-assets-jquery (>= 1.6)
rails-assets-jquery.slimscroll (1.3.3)
rails-assets-jquery (>= 1.7)
rails-assets-perfect-scrollbar (0.5.7)
rails-assets-jquery (>= 1.10)
rails-assets-punycode (1.3.2)
@ -553,7 +581,9 @@ DEPENDENCIES
cucumber-rails (= 1.4.2)
database_cleaner (= 1.3.0)
devise (= 3.4.1)
devise-token_authenticatable (~> 0.3.0)
devise_lastseenable (= 0.0.4)
diaspora-vines (~> 0.1.25)
entypo-rails (= 2.2.2)
factory_girl_rails (= 4.5.0)
faraday (= 0.9.0)
@ -600,6 +630,7 @@ DEPENDENCIES
rack-rewrite (= 1.5.0)
rack-ssl (= 1.4.1)
rails (= 4.1.7)
rails-assets-diaspora_jsxc (~> 0.0.4)
rails-assets-jeresig--jquery.hotkeys (= 0.2.0)
rails-assets-jquery (= 1.11.1)
rails-assets-jquery-idletimer (= 1.0.1)

View file

@ -1,2 +1,3 @@
web: bundle exec unicorn_rails -c config/unicorn.rb -p $PORT
sidekiq: bundle exec sidekiq
xmpp: bundle exec vines start

View file

@ -6,6 +6,7 @@ app.views.Contacts = Backbone.View.extend({
events: {
"click #contacts_visibility_toggle" : "toggleContactVisibility",
"click #chat_privilege_toggle" : "toggleChatPrivilege",
"click #change_aspect_name" : "showAspectNameForm",
"click .contact_remove-from-aspect" : "removeContactFromAspect",
"click .contact_add-to-aspect" : "addContactToAspect",
@ -14,12 +15,29 @@ app.views.Contacts = Backbone.View.extend({
initialize: function() {
this.visibility_toggle = $("#contacts_visibility_toggle .entypo");
this.chat_toggle = $("#chat_privilege_toggle .entypo");
$("#people_stream.contacts .header .entypo").tooltip({ 'placement': 'bottom'});
$(".contact_remove-from-aspect").tooltip();
$(".contact_add-to-aspect").tooltip();
$(document).on('ajax:success', 'form.edit_aspect', this.updateAspectName);
},
toggleChatPrivilege: function() {
if (this.chat_toggle.hasClass("enabled")) {
this.chat_toggle.tooltip("destroy")
.removeClass("enabled")
.removeAttr("data-original-title")
.attr("title", Diaspora.I18n.t("contacts.aspect_chat_is_not_enabled"))
.tooltip({'placement': 'bottom'});
} else {
this.chat_toggle.tooltip("destroy")
.addClass("enabled")
.removeAttr("data-original-title")
.attr("title", Diaspora.I18n.t("contacts.aspect_chat_is_enabled"))
.tooltip({'placement': 'bottom'});
}
},
toggleContactVisibility: function() {
if (this.visibility_toggle.hasClass("lock-open")) {
this.visibility_toggle.removeClass("lock-open")

View file

@ -0,0 +1,43 @@
//= require diaspora_jsxc
// initialize jsxc xmpp client
$(document).ready(function() {
if (app.currentUser.authenticated()) {
$.post('api/v1/tokens', null, function(data) {
if (jsxc && data['token']) {
var jid = app.currentUser.get('diaspora_id');
jsxc.init({
root: '/assets/diaspora_jsxc',
checkFlash: false,
logoutElement: $('.user-menu-item [data-method=delete]'),
rosterAppend: 'body',
otr: {
debug: true,
SEND_WHITESPACE_TAG: true,
WHITESPACE_START_AKE: true
},
autoLang: true,
priority: {
online: 1,
chat: 1
},
xmpp: {
url: $('script#jsxc').data('endpoint'),
username: jid.replace(/@.*?$/g, ''),
domain: jid.replace(/^.*?@/g, ''),
jid: jid,
password: data['token'],
resource: 'diaspora-jsxc',
overwrite: true,
onlogin: true
}
});
// TODO unset debug on default (testing version)
jsxc.storage.setItem('debug', true);
jsxc.login();
} else {
console.error('No token found! Authenticated!?');
}
}, 'json');
}
});

View file

@ -39,11 +39,12 @@
}
#new_aspect {
#aspect_contacts_visible.checkbox {
.checkbox {
margin: 0px;
}
label[for="aspect_contacts_visible"] {
label[for="aspect_contacts_visible"],
label[for="aspect_chat_enabled"] {
display: inline;
}
}

View file

@ -24,6 +24,9 @@
text-decoration: none;
margin-right: 25px;
}
#chat_privilege_toggle > .enabled {
color: #000;
}
.entypo.contacts-header-icon {
font-size: 24.5px;
line-height: 40px;

View file

@ -11,4 +11,5 @@
*= require vendor/autoSuggest
*= require entypo-fonts
*= require entypo
*= require diaspora_jsxc
*/

View file

@ -0,0 +1,16 @@
class Api::V1::TokensController < ApplicationController
skip_before_filter :verify_authenticity_token
before_filter :authenticate_user!
respond_to :json
def create
current_user.ensure_authentication_token!
render :status => 200, :json => { :token => current_user.authentication_token }
end
def destroy
current_user.reset_authentication_token!
render :json => true, :status => 200
end
end

View file

@ -78,6 +78,14 @@ class AspectsController < ApplicationController
render :json => { :id => @aspect.id, :name => @aspect.name }
end
def toggle_chat_privilege
@aspect = current_user.aspects.where(:id => params[:aspect_id]).first
@aspect.chat_enabled = !@aspect.chat_enabled
@aspect.save
render :nothing => true
end
def toggle_contact_visibility
@aspect = current_user.aspects.where(:id => params[:aspect_id]).first
@ -102,6 +110,6 @@ class AspectsController < ApplicationController
end
def aspect_params
params.require(:aspect).permit(:name, :contacts_visible, :order_id)
params.require(:aspect).permit(:name, :contacts_visible, :chat_enabled, :order_id)
end
end

View file

@ -7,4 +7,10 @@ class SessionsController < Devise::SessionsController
layout ->(c) { request.format == :mobile ? "application" : "with_header_with_footer" }, :only => [:new]
use_bootstrap_for :new
after_filter :reset_authentication_token, :only => [:create]
before_filter :reset_authentication_token, :only => [:destroy]
def reset_authentication_token
current_user.reset_authentication_token!
end
end

View file

@ -0,0 +1,13 @@
module JsxcHelper
def get_bosh_endpoint
port = AppConfig.chat.server.bosh.port
bind = AppConfig.chat.server.bosh.bind
host = AppConfig.pod_uri.host
scheme = AppConfig.pod_uri.scheme
unless AppConfig.chat.server.bosh.proxy?
return "http://#{host}:#{port}#{bind}"
end
return "#{scheme}://#{host}#{bind}"
end
end

View file

@ -16,7 +16,7 @@ class User < ActiveRecord::Base
scope :yearly_actives, ->(time = Time.now) { logged_in_since(time - 1.year) }
scope :halfyear_actives, ->(time = Time.now) { logged_in_since(time - 6.month) }
devise :database_authenticatable, :registerable,
devise :token_authenticatable, :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:lockable, :lastseenable, :lock_strategy => :none, :unlock_strategy => :none

View file

@ -21,6 +21,10 @@
= aspect.check_box :contacts_visible, :checked => false, class: 'checkbox'
= aspect.label :contacts_visible, t('aspects.edit.make_aspect_list_visible')
%p.checkbox_select
= aspect.check_box :chat_enabled, :checked => false, class: 'checkbox'
= aspect.label :chat_enabled, t('aspects.edit.grant_contacts_chat_privilege')
%br
.bottom_submit_section

View file

@ -10,6 +10,12 @@
-else
%i.entypo.lock.contacts-header-icon{:title => t('aspects.edit.aspect_list_is_not_visible')}
= link_to aspect_toggle_chat_privilege_path(@aspect), id: "chat_privilege_toggle", class: "contacts_button", method: :put, remote: true do
-if @aspect.chat_enabled?
%i.entypo.chat.enabled.contacts-header-icon{:title => t('aspects.edit.aspect_chat_is_enabled')}
-else
%i.entypo.chat.contacts-header-icon{:title => t('aspects.edit.aspect_chat_is_not_enabled')}
= link_to @aspect, method: "delete", data: { confirm: t('aspects.edit.confirm_remove_aspect') }, class: 'delete contacts_button', id: 'delete_aspect' do
%i.entypo.trash.contacts-header-icon{:title => t('delete')}
.pull-right

View file

@ -4,6 +4,9 @@
- content_for :head do
= javascript_include_tag :home
- if AppConfig.chat.enabled?
= javascript_include_tag :jsxc, :id => 'jsxc',
:data => { :endpoint => get_bosh_endpoint }
- if current_user.getting_started?
#welcome-to-diaspora

View file

@ -60,6 +60,7 @@ module Diaspora
jquery-textchange.js
mailchimp.js
main.js
jsxc.js
mobile.js
profile.js
people.js

View file

@ -40,6 +40,34 @@ defaults:
unicorn_timeout: 90
embed_sidekiq_worker: false
sidekiq_workers: 1
chat:
enabled: false
server:
enabled: true
certs: 'config/vines'
accept_self_signed: false
cross_domain_messages: true
max_offline_msgs: 150
c2s:
address: '0.0.0.0'
port: 5222
max_stanza_size: 65536
max_resources_per_account: 5
s2s:
address: '0.0.0.0'
port: 5269
max_stanza_size: 131072
blacklist: []
bosh:
proxy: false
address: '0.0.0.0'
port: 5280
bind: '/http-bind'
max_stanza_size: 65536
max_resources_per_account: 5
log:
file: 'log/vines.log'
level: 'info'
privacy:
jquery_cdn: false
google_analytics_key:

View file

@ -169,6 +169,102 @@ configuration: ## Section
## increase environment.sidekiq.concurrency instead!
#sidekiq_workers: 1
## Diaspora has a internal XMPP server. If you like a chat or want
## to use a custom server then you should touch following configuration
##
## The internal xmpp server does not support https
## and even if we implement it, we would ran into certificate issues.
## The problem with mixed-content is described here:
## https://github.com/Zauberstuhl/diaspora/issues/6
##
## The easiest way of avoiding certificate and mixed-content issues
## is to use a proxy, e.g.:
##
## Apache: https://gist.github.com/Zauberstuhl/2d09330961614b12b642
## Nginx: https://gist.github.com/Zauberstuhl/ee95e1eacefa6ddbec6e
##
## If you configured your proxy correctly you should adjust
## the configuration in the BOSH section
chat: ## Section
## Enable the chat and all his components
#enabled: true
## Custom XMPP server configuration goes here
server: ## Section
## If you have a own XMPP server you can disable the default one
#enabled: false
# Set the directory in which to look for virtual hosts' TLS certificates
#certs: 'config/vines'
# The server accepts on default only valid certificates.
# Any connection which uses self-signed will be closed.
# If you'd like to accept self-signed certificates
# on your server set the next option to true
#accept_self_signed: true
# Only touch the next option if you'd like to deny
# your user to exchange messages between other XMPP server
#cross_domain_messages: false
# Set the maximum of offline messages stored per user (default=150).
# If it exceeds it will start deleting old messages. You can disable
# offline message support completely by setting the option to zero.
#max_offline_msgs: 150
## client to server
c2s: ## Section
# Configure the address vines should listen on
#address: '0.0.0.0'
# Configure the client-to-server port
#port: 5222
# The maximum we'd like to allow for stanza size
#max_stanza_size: 65536
# The max_resources_per_account attribute limits how many
# concurrent connections one user can have to the server
#max_resources_per_account: 5
# server to server
s2s: ## Section
# Configure the address vines should listen on
#address: '0.0.0.0'
# Configure the server-to-server port
#port: 5269
# The max_stanza_size attribute should be
# much larger than the setting for client-to-server
#max_stanza_size: 131072
# On default every xmpp server with a valid certificate
# is able to communicate with your server. In case of
# malicous server (e.g. spam reason) you can black-list them:
#blacklist:
# - 'example.com'
# - 'malicous.net'
# XEP-0124 BOSH requests
bosh: ## Section
# If you'd like to use a proxy you should set the proxy
# option to true, otherwise jsxc always tries to
# connect directly to the port specified below
#proxy: true
# Configure the address vines should listen on
#address: '0.0.0.0'
# Configure the BOSH port
#port: 5280
# Configure the bind endpoint
#bind: '/http-bind'
# The maximum we'd like to allow for stanza size
#max_stanza_size: 65536
# The max_resources_per_account attribute limits how many
# concurrent connections one user can have to the server
#max_resources_per_account: 5
# Specify log behaviour here
log: ## Section
# log file location
#file: 'log/vines.log'
# Set the logging level to debug, info, warn, error, or fatal. The debug
# level logs all XML sent and received by the server.
#level: 'info'
## Settings potentially affecting the privacy of your users
privacy: ## Section

View file

@ -180,6 +180,7 @@ en:
contacts_visible: "Contacts in this aspect will be able to see each other."
contacts_not_visible: "Contacts in this aspect will not be able to see each other."
edit:
grant_contacts_chat_privilege: "grant contacts in aspect chat privilege?"
make_aspect_list_visible: "make contacts in this aspect visible to each other?"
remove_aspect: "Delete this aspect"
confirm_remove_aspect: "Are you sure you want to delete this aspect?"
@ -190,6 +191,8 @@ en:
rename: "rename"
aspect_list_is_visible: "Contacts in this aspect are able to see each other."
aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other."
aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you."
aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you."
update: "update"
updating: "updating"
aspect_contacts:

View file

@ -6,6 +6,7 @@ require 'sidekiq/web'
require 'sidetiq/web'
Diaspora::Application.routes.draw do
resources :report, :except => [:edit, :new]
if Rails.env.production?
@ -64,6 +65,7 @@ Diaspora::Application.routes.draw do
resources :aspects do
put :toggle_contact_visibility
put :toggle_chat_privilege
end
get 'bookmarklet' => 'status_messages#bookmarklet'
@ -208,6 +210,9 @@ Diaspora::Application.routes.draw do
get "/users/:username" => 'users#show', :as => 'user'
get "/tags/:name" => 'tags#show', :as => 'tag'
end
namespace :v1 do
resources :tokens, :only => [:create, :destroy]
end
end
get 'community_spotlight' => "contacts#spotlight", :as => 'community_spotlight'

7
config/vines/README Normal file
View file

@ -0,0 +1,7 @@
If you want to encrypt your chat streams with vines.
Add to `config/vines` your server certificate and key.
The domain name should be included in the file name e.g.:
* example.com.crt
* example.com.key

View file

@ -0,0 +1,16 @@
class CreateChatContacts < ActiveRecord::Migration
def up
create_table :chat_contacts do |t|
t.integer :user_id, null: false
t.string :jid, null: false
t.string :name, limit: 255, null: true
t.string :ask, limit: 128, null: true
t.string :subscription, limit: 128, null: false
end
add_index :chat_contacts, [:user_id, :jid], unique: true
end
def down
drop_table :chat_contacts
end
end

View file

@ -0,0 +1,17 @@
class CreateChatFragments < ActiveRecord::Migration
def up
create_table :chat_fragments do |t|
t.integer :user_id, null: false
t.string :root, limit: 256, null: false
t.string :namespace, limit: 256, null: false
t.text :xml, null: false
end
# That'll wont work due UTF-8 and the limit of 767 bytes
#add_index :chat_fragments, [:user_id, :root, :namespace], unique: true
add_index :chat_fragments, [:user_id], unique: true
end
def down
drop_table :chat_fragments
end
end

View file

@ -0,0 +1,9 @@
class AddChatEnabledToAspects < ActiveRecord::Migration
def self.up
add_column :aspects, :chat_enabled, :boolean, default: false
end
def self.down
remove_column :aspects, :chat_enabled
end
end

View file

@ -0,0 +1,14 @@
class CreateChatOfflineMessages < ActiveRecord::Migration
def self.up
create_table :chat_offline_messages do |t|
t.string :from, :null => false
t.string :to, :null => false
t.text :message, :null => false
t.datetime "created_at", :null => false
end
end
def self.down
drop_table :chat_offline_messages
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20141001162851) do
ActiveRecord::Schema.define(version: 20141024170120) do
create_table "account_deletions", force: true do |t|
t.string "diaspora_handle"
@ -43,12 +43,13 @@ ActiveRecord::Schema.define(version: 20141001162851) do
add_index "aspect_visibilities", ["shareable_id", "shareable_type"], name: "index_aspect_visibilities_on_shareable_id_and_shareable_type", using: :btree
create_table "aspects", force: true do |t|
t.string "name", null: false
t.integer "user_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "contacts_visible", default: true, null: false
t.string "name", null: false
t.integer "user_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "contacts_visible", default: true, null: false
t.integer "order_id"
t.boolean "chat_enabled", default: false
end
add_index "aspects", ["user_id", "contacts_visible"], name: "index_aspects_on_user_id_and_contacts_visible", using: :btree
@ -59,6 +60,32 @@ ActiveRecord::Schema.define(version: 20141001162851) do
t.integer "person_id"
end
create_table "chat_contacts", force: true do |t|
t.integer "user_id", null: false
t.string "jid", null: false
t.string "name"
t.string "ask", limit: 128
t.string "subscription", limit: 128, null: false
end
add_index "chat_contacts", ["user_id", "jid"], name: "index_chat_contacts_on_user_id_and_jid", unique: true, using: :btree
create_table "chat_fragments", force: true do |t|
t.integer "user_id", null: false
t.string "root", limit: 256, null: false
t.string "namespace", limit: 256, null: false
t.text "xml", null: false
end
add_index "chat_fragments", ["user_id"], name: "index_chat_fragments_on_user_id", unique: true, using: :btree
create_table "chat_offline_messages", force: true do |t|
t.string "from", null: false
t.string "to", null: false
t.text "message", null: false
t.datetime "created_at", null: false
end
create_table "comments", force: true do |t|
t.text "text", null: false
t.integer "commentable_id", null: false

View file

@ -75,7 +75,10 @@ vars=$(bundle exec ruby ./script/get_config.rb \
port=server.port \
single_process_mode=environment.single_process_mode? \
embed_sidekiq_worker=server.embed_sidekiq_worker \
workers=server.sidekiq_workers
workers=server.sidekiq_workers \
chat=chat.enabled \
chat_server=chat.server.enabled \
chat_bosh_proxy=chat.server.bosh.proxy
)
on_failure "Couldn't parse config/diaspora.yml!"
eval "$vars"
@ -137,6 +140,24 @@ https://github.com/diaspora/diaspora/issues/4202 for details
"
fi
vines=0
if [ "$chat" = "true" ] && [ "$chat_server" = "true" ]
then
vines=1
if [ "$chat_bosh_proxy" = "false" ]
then
warning "
*****************************************************************
You enabled the chat feature but haven't configured BOSH! That
could lead to mixed-content problems with the http clients. Please
think about editing your proxy configuration as described in:
diaspora.yml.example
*****************************************************************
"
fi
fi
# Start Diaspora
echo -n "Starting Diaspora in $RAILS_ENV mode on port $port "
if [ "$embed_sidekiq_worker" = "true" ]
@ -152,4 +173,4 @@ else
fi
echo ""
exec bundle exec foreman start -m "web=1,sidekiq=$workers" -p $port
exec bundle exec foreman start -m "xmpp=$vines,web=1,sidekiq=$workers" -p $port

View file

@ -210,11 +210,11 @@ describe UsersController, :type => :controller do
expect(assigns[:email_prefs]['mentioned']).to be false
end
it 'does not allow token auth' do
it 'does allow token auth' do
sign_out :user
bob.reset_authentication_token!
get :edit, :auth_token => bob.authentication_token
expect(response).to redirect_to new_user_session_path
expect(response.status).to eq(200)
end
end

View file

@ -0,0 +1,21 @@
require 'spec_helper'
describe JsxcHelper, :type => :helper do
before do
AppConfig.chat.server.bosh.proxy = false
AppConfig.chat.server.bosh.port = 1234
AppConfig.chat.server.bosh.bind = '/bind'
AppConfig.environment.url = "https://localhost/"
end
describe "#get_bosh_endpoint" do
it "using http scheme and default values" do
expect(helper.get_bosh_endpoint).to include %Q(http://localhost:1234/bind)
end
it "using https scheme and no port" do
AppConfig.chat.server.bosh.proxy = true
expect(helper.get_bosh_endpoint).to include %Q(https://localhost/bind)
end
end
end

View file

@ -7,6 +7,8 @@ describe("app.views.Contacts", function(){
add_contact: "Add contact",
aspect_list_is_visible: "Contacts in this aspect are able to see each other.",
aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other.",
aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you.",
aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you.",
remove_contact: "Remove contact",
error_add: "Couldn't add <%= name %> to the aspect :(",
error_remove: "Couldn't remove <%= name %> from the aspect :("
@ -14,6 +16,29 @@ describe("app.views.Contacts", function(){
});
});
context('toggle chat privilege', function() {
beforeEach(function() {
this.chat_toggle = $("#chat_privilege_toggle");
this.chat_icon = $("#chat_privilege_toggle .entypo");
});
it('updates the title for the tooltip', function() {
expect(this.chat_icon.attr('data-original-title')).toBe(
Diaspora.I18n.t("contacts.aspect_chat_is_not_enabled")
);
this.chat_toggle.trigger('click');
expect(this.chat_icon.attr('data-original-title')).toBe(
Diaspora.I18n.t("contacts.aspect_chat_is_enabled")
);
});
it('toggles the chat icon', function() {
expect(this.chat_icon.hasClass('enabled')).toBeFalsy;
this.chat_toggle.trigger('click');
expect(this.chat_icon.hasClass('enabled')).toBeTruethy;
});
});
context('toggle contacts visibility', function() {
beforeEach(function() {
this.visibility_toggle = $("#contacts_visibility_toggle");