Merge pull request #61 from coopdevs/languages_cont

Languages cont:

- Locale support and translations to spanish, catalan and english
- User creation now redirects to user list (/members)
- Deactivated users show with red background in list
- RSpec tests all existing ones are passing now again
- Includs Stub for browser locale simulation and added Capybara for flag selection test and redirection
This commit is contained in:
Daniel Macho
2014-11-17 10:25:49 +01:00
31 changed files with 1235 additions and 29 deletions
+1
View File
@@ -68,6 +68,7 @@ end
group :development, :test do
gem "rspec-rails", '~> 2.14'
gem "capybara", '~> 2.4.4'
end
group :test do
+12
View File
@@ -72,6 +72,12 @@ GEM
sass (~> 3.3)
thor
builder (3.2.2)
capybara (2.4.4)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
choice (0.1.6)
coderay (1.1.0)
coffee-rails (4.0.1)
@@ -146,10 +152,13 @@ GEM
treetop (~> 1.4.8)
memcachier (0.0.2)
mime-types (1.25.1)
mini_portile (0.6.1)
minitest (5.3.4)
multi_json (1.10.1)
ngannotate-rails (0.9.2)
rails (>= 3.1)
nokogiri (1.6.4.1)
mini_portile (~> 0.6.0)
orm_adapter (0.5.0)
paranoia (2.0.0)
activerecord (~> 4.0)
@@ -257,6 +266,8 @@ GEM
multi_json (~> 1.0, >= 1.0.2)
warden (1.2.3)
rack (>= 1.0)
xpath (2.0.0)
nokogiri (~> 1.3)
PLATFORMS
ruby
@@ -266,6 +277,7 @@ DEPENDENCIES
awesome_print
better_errors
binding_of_caller
capybara (~> 2.4.4)
coffee-rails
dalli
database_cleaner
+3
View File
@@ -0,0 +1,3 @@
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
@@ -11,6 +11,8 @@
*= require_self
*/
@import "flags";
.post {
border-top: solid black 1px;
list-style: none;
+3
View File
@@ -0,0 +1,3 @@
// Place all the styles related to the global controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
+19 -2
View File
@@ -1,5 +1,6 @@
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
before_filter :setup_vars
include Pundit
protect_from_forgery
@@ -18,9 +19,16 @@ class ApplicationController < ActionController::Base
def set_locale
if params[:locale]
session[:locale] = params[:locale]
locale=params[:locale]
session[:locale] = locale
else
locale=extract_locale_from_accept_language_header
end
I18n.locale = session[:locale] || I18n.default_locale
# we check that provided locale from browser is in our supported list of languages
# if not, we use the default from rails conf
session[:locale] ||= @supported_langs.include?(locale)? locale: I18n.default_locale.to_s
I18n.locale = session[:locale]
true
end
@@ -49,6 +57,9 @@ class ApplicationController < ActionController::Base
end
end
def setup_vars
@supported_langs=%w(es ca en)
end
private
@@ -79,4 +90,10 @@ class ApplicationController < ActionController::Base
def authenticate_superuser!
superuser? || redirect_to(root_path)
end
# To get locate from client supplied information
# see http://guides.rubyonrails.org/i18n.html#setting-the-locale-from-the-client-supplied-information
def extract_locale_from_accept_language_header
request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first
end
end
+26
View File
@@ -0,0 +1,26 @@
class GlobalController < ApplicationController
def switch_lang
set_locale
if current_user and current_organization
redirect_to offers_path
else
go_home
end
end
def go_home
l = session[:locale]
case l
when 'es'
url='home'
else
url='home_'+l
end
redirect_to page_path(url)
end
end
+1 -1
View File
@@ -44,7 +44,7 @@ class UsersController < ApplicationController
if @user.persisted?
@user.add_to_organization current_organization
redirect_to @user
redirect_to users_path
else
redirect_to :action => "new"
end
+2
View File
@@ -0,0 +1,2 @@
module GlobalHelper
end
+14 -2
View File
@@ -1,7 +1,7 @@
%nav.navbar.navbar-static-top.navbar-inverse{role: :navigation}
.container
.navbar-header
%a.navbar-brand(href="/") TimeOverflow
%a.navbar-brand(href="/global/go_home") TimeOverflow
%ul.nav.navbar-nav
- if current_user and current_organization
@@ -81,8 +81,20 @@
= link_to m.organization do
= glyph(:pencil)
= t "layouts.application.edit_org", organization: m.organization
- else
%li
%a{href: new_user_session_path}
= t "layouts.application.login"
%li.divider{role: :presentation}
%li{role: :presentation}
= link_to "/global/switch_lang?locale=es", id: 'es_flag' do
= image_tag("blank.png",{class: "flag flag-es", alt: "Español"})
%li{role: :presentation}
= link_to "/global/switch_lang?locale=ca", id: 'ca_flag' do
= image_tag("blank.png",{class: "flag flag-catalonia", alt: "Català"})
%li{role: :presentation}
= link_to "/global/switch_lang?locale=en", id: 'en_flag' do
= image_tag("blank.png",{class: "flag flag-gb", alt: "English"})
+2
View File
@@ -0,0 +1,2 @@
%h1 Global#switch_lang
%p Find me in app/views/global/switch_lang.html.haml
+66
View File
@@ -0,0 +1,66 @@
= content_for :window_title do
TimeOverflow - Gestió on-line de Bancs de Temps
.container-inner
- if current_user and !current_organization
= render 'organization_list'
.row
.col-sm-6
.text-center
%h1 TimeOverflow
= image_tag "sand-clock.png", width: 50
%h2 El software disenyat per i per als Bancs de Temps
%em TimeOverflow és lliure, gratuït i col·laboratiu
.text-left{style: "margin-top: 40px;"}
:markdown
Funcionalitats de **TimeOverflow**:
* Gestió del Banc de Temps amb perfils d'administració
* Altes/baixes/modificacions de membres
* Publicar ofertes i demandes
* Introduir xecs i gestionar la comptabilitat
* Xarxa social i banca en línia accessible pels membres
* Els membres d'un Banc de Temps poden accedir al sistema i contactar amb altres membres
* Publicar ofertes i demandes
* Pagar hores a altres membres
%h2 Ets un Banc de Temps?
.text-center
%a.btn.btn-primary.btn-large{href: "http://adbdt.org/ca/contacta/", style:"font-size:30px;margin-top:20px;"}
Sol·licita accés a TimeOverflow
.text-center
%p
%em (ens posarem en contacte amb tu per posar-lo en marxa o fer-vos una demostració)
.col-sm-6
.text-center
%h2 Ja ets membre d'un Banc de Temps que fa servir TimeOverflow?
%a.btn.btn-primary.btn-large{href: new_user_session_path, style:"font-size:30px;margin-top:20px;"}
Entra aquí
%p
:markdown
Si ets una persona interessada a participar en un Banc de Temps,
busca el teu Banc de Temps més proper a
[bdtonline.org](http://www.bdtonline.org "Bancs de Temps").
= image_tag "oferta.png", class: "img-responsive center-block"
%h2 Internet potencia els Bancs de Temps
:markdown
TimeOveflow està especialment dissenyat ** per i per als Bancs de Temps **
que existeixen físicament([veure mapa](http://www.bdtonline.org "Bancs de Temps")),
la seva fi és potenciar gràcies a Internet.
Gràcies al treball conjunt de [CoopDevs](https://github.com/coopdevs)
i la [ADBdT](http://adbdt.org/ca "Associació per al Desenvolupament dels Bancs de Temps")
avui podem oferir el sofware **TimeOverflow** a tots els Bancs de
Temps que així ho desitgin de manera lliure i gratuïta.
El codi font de TimeOverflow està disponible sota una llicència
open source, ja es pot descarregar a [https://github.com/coopdevs/timeoverflow](https://github.com/coopdevs/timeoverflow)
.text-center
= link_to "https://github.com/coopdevs/timeoverflow", title: "TimeOverflow Github" do
= image_tag("github.png", alt: "Github logo", height: 30)
+66
View File
@@ -0,0 +1,66 @@
= content_for :window_title do
TimeOverflow - Time Bank on-line management
.container-inner
- if current_user and !current_organization
= render 'organization_list'
.row
.col-sm-6
.text-center
%h1 TimeOverflow
= image_tag "sand-clock.png", width: 50
%h2 The software designed by and for Time Banks
%em TimeOverflow is open source, free and collaborative
.text-left{style: "margin-top: 40px;"}
:markdown
Features of **TimeOverflow**:
* Time Bank management with administration roles
* Creation/deletion/updates of bank members
* Posting of offers and inquiries
* Enter checks and manage accounting
* Social network and online banking accessible by members
* Members of a Time Bank can access the system and connect with other members
* Posting of offers and inquiries
* Pay hours to other members
%h2 Are you a Time Bank?
.text-center
%a.btn.btn-primary.btn-large{href: "http://adbdt.org/contacta/", style:"font-size:30px;margin-top:20px;"}
Request access to TimeOverflow
.text-center
%p
%em (We will contact you to start it up or make you a demonstration)
.col-sm-6
.text-center
%h2 Already a member of a Time Bank that uses TimeOverflow?
%a.btn.btn-primary.btn-large{href: new_user_session_path, style:"font-size:30px;margin-top:20px;"}
Click here
%p
:markdown
If you are a person interested in participating in a Time Bank,
find your closest Time Bank at
[bdtonline.org](http://www.bdtonline.org "Bancos de Tiempo").
= image_tag "oferta.png", class: "img-responsive center-block"
%h2 Internet enhances Time Banks activity
:markdown
TimeOveflow is specially designed **for and by Time Banks**
that physically exist ([see map](http://www.bdtonline.org "Bancos de Tiempo")),
and its purpose is to boost them thanks to Internet.
Thanks to the joint job of [CoopDevs](https://github.com/coopdevs)
and [ADBdT](http://adbdt.org "Association for the Development of Time Banks")
today que can offer the software **TimeOverflow** to all Time Banks
that want it, open and for free.
The source code of TimeOverflow is available based on an open source
license and you can download it at [https://github.com/coopdevs/timeoverflow](https://github.com/coopdevs/timeoverflow)
.text-center
= link_to "https://github.com/coopdevs/timeoverflow", title: "TimeOverflow Github" do
= image_tag("github.png", alt: "Github logo", height: 30)
+1 -2
View File
@@ -1,4 +1,4 @@
%tr{ "ng-repeat" => "user in users | orderBy:sort | filter:filterTerm" }
%tr{ "ng-repeat" => "user in users | orderBy:sort | filter:filterTerm", "ng-class" => "{'bg-danger': !user.active}" }
%td
%img{ "ng-src" => "{{user.avatar}}", height: "32px", width: "32px" }
%td {{user.member_id}}
@@ -38,4 +38,3 @@
%span{ "ng-if" => "!user.active" }
.glyphicon.glyphicon-ok
= t ".activate"
+14 -14
View File
@@ -21,13 +21,13 @@ ca:
one: Demanda
other: Demandes
transfer:
one: Transferencia
one: Transferència
other: Transferències
post:
one: Anuncio
other: Anuncios
one: Anunci
other: Anuncis
comment:
one: Comentario
one: Comentari
other: Comentaris
attributes:
@@ -41,7 +41,7 @@ ca:
one: Banc de Temps
other: Bancs de Temps
email: Correu
registration_date: Data de alta
registration_date: Data d'alta
gender: Gènere
registration_number: Codi d'usuari
date_of_birth: Data de naixement
@@ -68,7 +68,7 @@ ca:
<<: *common_attributes
name: Nom
parent: Categoria pare
name_translations: Nom (traducciones)
name_translations: Nom (traduccions)
transfer:
<<: *common_attributes
amount: Quantitat
@@ -82,8 +82,8 @@ ca:
tag_list: Etiquetes
joinable: Es poden afegir altres
permanent: Permanent
start_on: Comença el
end_on: Finalitza el
start_on: Comença al
end_on: Finalitza al
# ETIQUETAS VARIADAS EN PLANTILLAS
@@ -106,7 +106,7 @@ ca:
sing_out: Desconnectar
organization_list:
welcome: Benvingut a Timeoverflow %{user}.
not_member: No ets membre de cap Banc de Temps, per fer servir el sistema hauràs de possar-te en contcat amb un dels Bancs de Temps del sistema
not_member: No ets membre de cap Banc de Temps, per fer servir el sistema hauràs de possar-te en contacte amb un dels Bancs de Temps del sistema
time_bank: Banc de Temps
email: Correu
phone: Telèfon
@@ -116,7 +116,7 @@ ca:
neighborhood: Barri
city: Ciutat
tips:
entertag: Introdueix etiquetes separadas per comes
entertag: Introdueix etiquetes separades per comes
user_not_found: "Usuari no trobat."
# views/users/index...
@@ -210,7 +210,7 @@ ca:
no_movements: Sense intercanvis
days_without_swaps: Dies sense intercanvis
demographics: Dades demogràfiques
by_ages: Por edats
by_ages: Per edats
num_people: "Nombre de Persones"
unknown: Desconegut
@@ -247,13 +247,13 @@ ca:
save: Desar
add_new: Crear nou
cancel_membership: Esborrar definitivament
back: Enrrere
back: Enrere
give_time: Transferir temps
filter: Filtre
all: Tot
search: Cercar
information: Informació
member_count: "Nombre d'usuarios:"
member_count: "Nombre d'usuaris:"
balance: 'Balanç:'
movements: Moviments
date: Data
@@ -272,7 +272,7 @@ ca:
layouts:
application:
login: Entrar
edit_profile: Modificarb perfil
edit_profile: Modificar perfil
edit_org: "Modificar %{organization}"
report:
report_title: "INFORME"
+3 -3
View File
@@ -25,7 +25,7 @@ ca:
locked: "El teu compte ha estat bloquejat."
not_found_in_database: "Correu o clau invàlida."
timeout: "La teva sessió ha caducat. Si us plau, torna a entrar per continuar."
unauthenticated: "Has que entrar per continuar."
unauthenticated: "Has de entrar per continuar."
unconfirmed: "Has de confiramar el teu compte abans de continuar."
mailer:
confirmation_instructions:
@@ -35,7 +35,7 @@ ca:
unlock_instructions:
subject: "Instruccions de desbloqueig del compte"
omniauth_callbacks:
failure: "No s'ha pogut autentificar desde %{kind} perque \"%{reason}\"."
failure: "No s'ha pogut autentificar desde %{kind} perquè \"%{reason}\"."
success: "Autentificació realitzada desde el compte %{kind} ."
passwords:
no_token: "No pots accedir a aquesta pàgina si no vens d'un correu per restablir la contrasenya. Si vens d'un correu per a restablir la contrasenya, assegurat que has utilitzat la URL completa."
@@ -92,4 +92,4 @@ ca:
not_locked: "no es va bloquejar"
not_saved:
one: "1 error impedeix que aquest %{resource} es desi:"
other: "%{count} errors impedeix que aquest %{resource} es desi:"
other: "%{count} errors impedeixen que aquest %{resource} es desi:"
+11
View File
@@ -2,6 +2,14 @@
en:
devise:
shared:
links:
sign_in: "Login"
sign_up: "Register"
forgot_your_password: "I do not remember my password"
didnt_receive_confirmation_instructions: "Resend confirmation email"
didnt_receive_unlock_instructions: "Receive unlock instructions"
sign_in_with: "Login with %{provider}"
confirmations:
confirmed: "Your account was successfully confirmed."
confirmed_and_signed_in: "Your account was successfully confirmed. You are now signed in."
@@ -44,6 +52,9 @@ en:
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
new:
sign_in: "Login"
remember_me: "Remember me"
unlocks:
send_instructions: "You will receive an email with instructions about how to unlock your account in a few minutes."
send_paranoid_instructions: "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
+277 -4
View File
@@ -1,5 +1,278 @@
# Sample localization file for English. Add more files in this directory for other locales.
# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
en:
hello: "Hello world"
# NOMBRES DE LAS COSAS
activerecord:
models:
# Para usar:
# User.model_name.human
user:
one: User
other: Users
organization:
one: Time Bank
other: Time Banks
category:
one: Category
other: Categories
offer:
one: Offer
other: Offers
inquiry:
one: Inquiry
other: Inquiries
transfer:
one: Transfer
other: Transfers
post:
one: Post
other: Posts
comment:
one: Comment
other: Comments
attributes:
common: &common_attributes
created_at: Created
updated_at: Updated
user:
<<: *common_attributes
username: Name
organization:
one: Time Bank
other: Time Banks
email: Email
registration_date: Registration date
gender: Gender
registration_number: User code
date_of_birth: Date of birth
identity_document: Identity Document
phone: Phone
alt_phone: Alternative Phone
admin: Organization Administrator
superadmin: System Administrator
description: Description
unconfirmed_email: Unconfirmed Email
organization:
<<: *common_attributes
name: Name
reg_number_seq: User sequence number
theme: Theme
email: Email
phone: Phone
public_opening_times: Opening hours
description: Description
address: Address
neighborhood: Neighborhood
city: City
category:
<<: *common_attributes
name: Name
parent: Parent category
name_translations: Name (translations)
transfer:
<<: *common_attributes
amount: Quantity
reason: Comments
source: Source
post:
<<: *common_attributes
title: Title
description: Description
category: Category
tag_list: Tags
joinable: Can join others
permanent: Permanent
start_on: Start on
end_on: Ends on
# ETIQUETAS VARIADAS EN PLANTILLAS
application:
terms_conditions: terms of service
navbar:
administration: Administration
reports: Reports
stats: Statistics
users: Users
categories: Services
organizations: Organizations
statistics: Statistics
admin: Manage
adminshort: Admin
tags: Tags
sign_out: Logout
menu:
sign_in: Login
sing_out: Logout
organization_list:
welcome: Welcome to Timeoverflow %{user}.
not_member: You do not belong to any time bank at this moment, in order to use this platform you need to keep in touch with one of the time banks that have joint the platform
time_bank: Time Bank
email: Email
phone: Phone
public_opening_times: Opening hours
description: Description
address: Address
neighborhood: Neighborhood
city: City
tips:
entertag: Enter tags separated by commas
user_not_found: "User not found."
# views/users/index...
users:
index:
create: Create new user
manage_warning_angular: "You are going to change privileges for user {{username}}"
cancel_warning_angular: "You are going to delete account from the Time Bank for user {{username}}"
active_warning_angular: "You are going to change user account status for {{username}}"
actions: Actions
new:
new_user: New user
show:
phone:
one: Phone
other: Phones
data: User details
categories: Offered Services
account: Last transactions
inactive: "(Inactive)"
accounts: Accounts
created_at: "Registered:"
user_no: "User #:"
balance: "Balance:"
movements: "Transactions"
date: Date
from_to: From/To
post: Post
reason: Reason
quantity: Quantity
give_time:
give_time: Give time to
form:
superadmin_warning: Warning!!! You are giving GOD PRIVILEGES to this user!!
admin_warning: Warning!!! You are giving privileges to this user!!
user_rows:
activate: Activate
deactivate: Deactivate
manage_warning: "You are going to change privileges for user %{user}"
cancel_warning: "You are going to delete account from the Time Bank for user %{user}"
active_warning: "You are going to change user account status for %{user}"
tags:
alpha_grouped_index:
maintitle: Available Tags
terms:
accept: Accept
offers:
index:
offered_by: "Offered by %{size} people"
new_offer: "New offer"
filter: Filter
by_category: By category
by_tag: By Tag
show:
offered_by: "Offered by"
new:
submit: Create offer
inquiries:
index:
new_inquiry: New inquiry
new:
submit: Create inquiry
categories:
index:
all: All
tree: Main
global: Global
local: Local
add: Add service
reports:
cat_with_users:
title: Offered Services
user_list:
title: User List
statistics:
statistics: Statistics
bank_activity: "Bank Activity"
per_month: "Per Month"
global_activity: "Global Activity"
users_reg: "Registered users"
num_swaps: "Transactions"
total_hours: "Hours transfered"
inactive_users: Inactive users
last_movement: Last transaction
no_movements: Without transactions
days_without_swaps: Days without transactions
demographics: Demographic data
by_ages: Per ages
num_people: "# of people"
unknown: Unknown
stats:
min_balance:
title: Users Minimum Balance
organizations:
index:
member_count: Number of users
new:
new: New bank
show:
contact_information: Contact information
give_time:
give_time: Give time to
transfers:
computation:
joiner: " and "
hour:
one: ! '%{count} hour'
other: ! '%{count} hours'
minute:
one: ! '%{count} minute'
other: ! '%{count} minutes'
global:
table:
actions: Actions
show: Show
edit: Update
delete: Delete
save: Save
add_new: Create new
cancel_membership: Permanent deletion
back: Back
give_time: Time transfer
filter: Filter
all: All
search: Search
information: Information
member_count: 'Number of users:'
balance: 'Balance:'
movements: Transactions
date: Data
source_destination: 'From/to'
announcements: Post
reason: Reason
amount: Quantity
demote: Demote to normal user
promote: Promote to administrator
active_admin:
comments:
resource_type: Resource type
author_type: Author type
layouts:
application:
login: Login
edit_profile: Update my profile
edit_org: "Update %{organization}"
report:
report_title: "REPORT"
+2
View File
@@ -1,4 +1,6 @@
Timeoverflow::Application.routes.draw do
get 'global/switch_lang'
get 'global/go_home'
get 'tags/index'
devise_for :users
+186
View File
@@ -0,0 +1,186 @@
require 'spec_helper'
describe GlobalController do
include_context "stub browser locale"
before { set_browser_locale('it') }
describe "User not logged and GET 'switch_lang' using browser's locale" do
subject { get 'switch_lang' }
context 'browser in spanish' do
it "redirects to spanish home" do
# We stub the method that extracts browsers language info and force to return expected value for
# context
set_browser_locale('es')
#response.should redirect to home spanish
subject.should redirect_to('/home')
end
end
context 'browser in catalan' do
it "redirects to spanish home" do
# We stub the method that extracts browsers language info and force to return expected value for
# context
set_browser_locale('ca')
#response.should redirect to home catalan
subject.should redirect_to('/home_ca')
end
end
context 'broser in english' do
it "redirects to spanish home" do
# We stub the method that extracts browsers language info and force to return expected value for
# context
set_browser_locale('en')
#response.should redirect to home english
subject.should redirect_to('/home_en')
end
end
context 'browser in non-supported language' do
it "redirects to spanish default home" do
# We stub the method that extracts browsers language info and force to return expected value for
# context
# We stub to an invalid locale to check it redirects to the right default one
set_browser_locale('fr')
#response.should redirect to default home (spanish)
subject.should redirect_to('/home')
end
end
end
describe "User not logged and GET 'switch_lang' by selection in navbar in english" do
subject { get 'switch_lang', {:locale => 'en'} }
it "redirects to english home" do
#response.should redirect to home_en
subject.should redirect_to('/home_en')
end
end
describe "User not logged and GET 'switch_lang' by selection in navbar in spanish" do
subject { get 'switch_lang', {:locale => 'es'} }
it "redirects to spanish home" do
#response.should redirect to home (spanish)
subject.should redirect_to('/home')
end
end
describe "User not logged and GET 'switch_lang' by selection in navbar in catalan" do
subject { get 'switch_lang', {:locale => 'ca'} }
it "redirects to catalan home" do
#response.should redirect to home_ca
subject.should redirect_to('/home_ca')
end
end
#
# Now with user logged in in different default browser languages
#
describe "User logged and GET 'switch_lang' using browser's locale" do
let! (:test_organization) { Fabricate(:organization)}
let! (:member) { Fabricate(:member, organization: test_organization) }
context 'browser in spanish' do
it "redirects to spanish offers page" do
# We stub the method that extracts browsers language info and force to return expected value for
# context
set_browser_locale('es')
login(member.user)
visit offers_path
current_path.should == "/offers"
page.body.should include('Ofertas')
end
end
context 'browser in catalan' do
it "redirects to catalan offers page" do
# We stub the method that extracts browsers language info and force to return expected value for
# context
set_browser_locale('ca')
login(member.user)
visit offers_path
current_path.should == "/offers"
page.body.should include('Ofertes')
end
end
context 'browser in catalan' do
it "redirects to catalan offers page" do
# We stub the method that extracts browsers language info and force to return expected value for
# context
set_browser_locale('en')
login(member.user)
visit offers_path
current_path.should == "/offers"
page.body.should include('Offers')
end
end
end
#
# Now with user logged in having selected language
#
describe "User logged and GET 'switch_lang' using browser's locale" do
let! (:test_organization) { Fabricate(:organization)}
let! (:member) { Fabricate(:member, organization: test_organization) }
context 'user clicks in Spanish flag' do
it "redirects to spanish offers page" do
visit '/'
click_link 'es_flag'
login(member.user)
visit offers_path
current_path.should == "/offers"
page.body.should include('Ofertas')
end
end
context 'user clicks in English flag' do
it "redirects to catalan offers page" do
visit '/'
click_link 'en_flag'
login(member.user)
visit offers_path
current_path.should == "/offers"
page.body.should include('Offers')
end
end
context 'user clicks in catalan flag' do
it "redirects to catalan offers page" do
visit '/'
click_link 'ca_flag'
login(member.user)
visit offers_path
current_path.should == "/offers"
page.body.should include('Ofertes')
end
end
end
end
@@ -5,6 +5,8 @@ describe InquiriesController do
let (:member) { Fabricate(:member, organization: test_organization)}
let (:another_member) { Fabricate(:member, organization: test_organization)}
let! (:inquiry) { Fabricate(:inquiry, user: member.user, organization: test_organization)}
include_context "stub browser locale"
before { set_browser_locale('ca') }
describe "GET #index" do
context "with a logged user" do
@@ -0,0 +1,86 @@
require 'spec_helper'
describe OffersController do
let (:test_organization) { Fabricate(:organization)}
let (:member) { Fabricate(:member, organization: test_organization)}
let (:another_member) { Fabricate(:member, organization: test_organization)}
let! (:offer) { Fabricate(:offer, user: member.user, organization: test_organization)}
include_context "stub browser locale"
before { set_browser_locale('ca') }
describe "GET #index" do
context "with a logged user" do
it "populates and array of offers" do
login(another_member.user)
get 'index'
expect(assigns(:offers)).to eq([offer])
end
end
end
describe "GET #show" do
context "with valid params" do
context "with a logged user" do
it "assigns the requested offer to @offer" do
login(another_member.user)
get 'show', id: offer.id
expect(assigns(:offer)).to eq(offer)
end
end
end
end
describe "POST #create" do
context "with valid params" do
context "with a logged user" do
it "creates a new offer" do
login(another_member.user)
expect {
post 'create', offer: Fabricate.to_params(:offer)
}.to change(Offer,:count).by(1)
end
end
end
end
describe "PUT #update" do
context "with valid params" do
context "with a logged user" do
it "located the requested @offer" do
login(member.user)
put 'update', id: offer.id, offer: Fabricate.to_params(:offer)
expect(assigns(:offer)).to eq(offer)
end
it "changes @offer's attributes" do
login(member.user)
put 'update', id: offer.id, offer: Fabricate.to_params(:offer, user: member, title: "New title", description: "New description")
offer.reload
expect(offer.title).to eq("New title")
expect(offer.description).to eq("New description")
end
end
end
context "with invalid params" do
context "with a logged user" do
it "does not change @offer's attributes" do
login(member.user)
put :update, id: offer.id, offer: Fabricate.to_params(:offer, user: nil, title: "New title", description: "New description")
expect(offer.title).not_to eq("New title")
expect(offer.description).not_to eq("New description")
end
end
end
end
end
+2
View File
@@ -1,6 +1,8 @@
require 'spec_helper'
describe TagsController do
include_context "stub browser locale"
before { set_browser_locale('it') }
describe "GET 'index'" do
it "returns http success" do
@@ -5,10 +5,13 @@ describe TransfersController do
let (:member_admin) { Fabricate(:member, organization: test_organization, manager: true)}
let (:member_giver) { Fabricate(:member, organization: test_organization) }
let (:member_taker) { Fabricate(:member, organization: test_organization) }
include_context "stub browser locale"
before { set_browser_locale('ca') }
describe "POST #create" do
before { login(user) }
context "with valid params" do
context "with an admin user logged" do
+146
View File
@@ -0,0 +1,146 @@
require 'spec_helper'
describe UsersController do
let (:test_organization) { Fabricate(:organization)}
let (:member_admin) { Fabricate(:member, organization: test_organization, manager: true)}
let (:member) { Fabricate(:member, organization: test_organization)}
let! (:user) { member.user }
let! (:admin_user) { member_admin.user}
include_context "stub browser locale"
before { set_browser_locale('ca') }
describe "GET #index" do
context "with an normal logged user" do
it "populates and array of users" do
login(member.user)
get 'index'
expect(assigns(:users)).to eq([user,admin_user])
end
end
context "with an admin logged user" do
it "populates and array of users" do
login(member_admin.user)
get 'index'
expect(assigns(:users)).to eq([user,admin_user])
end
end
end
describe "GET #show" do
context "with valid params" do
context "with a normal logged user" do
it "assigns the requested user to @user" do
login(member.user)
get 'show', id: user.id
expect(assigns(:user)).to eq(user)
end
end
context "with an admin logged user" do
it "assigns the requested user to @user" do
login(member_admin.user)
get 'show', id: user.id
expect(assigns(:user)).to eq(user)
end
end
end
end
describe "POST #create" do
context "with valid params" do
subject {post 'create', user: Fabricate.to_params(:user)}
context "with a normal logged user" do
it "does not create a new user" do
login(member.user)
# TODO:
# Expect exception...
#
expect {
post 'create', user: Fabricate.to_params(:user)
}.to change(User,:count).by(0)
end
end
context "with an admin logged user" do
it "creates a new user" do
login(member_admin.user)
expect {
subject
}.to change(User,:count).by(1)
subject.should redirect_to('/members')
end
end
end
end
describe "PUT #update" do
context "with valid params" do
context "with a logged" do
context "normal user" do
it "located the requested @user" do
login(member.user)
put 'update', id: user.id, user: Fabricate.to_params(:user)
expect(assigns(:user)).to eq(user)
end
#
# TODO RAISE EXCEPTION
#
it "changes @user's attributes" do
login(member.user)
put 'update', id: user.id, user: Fabricate.to_params(:user, username: user.username, email: user.email, phone:'1234', alt_phone: "4321")
user.reload
expect(user.phone).not_to eq("1234")
expect(user.alt_phone).not_to eq("4321")
end
end
context "admin user" do
it "located the requested @user" do
login(member_admin.user)
put 'update', id: user.id, user: Fabricate.to_params(:user)
expect(assigns(:user)).to eq(user)
end
it "changes @user's attributes" do
login(member_admin.user)
put 'update', id: user.id, user: Fabricate.to_params(:user, username: user.username, email: user.email, phone:'1234', alt_phone: "4321")
user.reload
expect(user.phone).to eq("1234")
expect(user.alt_phone).to eq("4321")
end
end
end
end
context "with invalid params" do
context "with a logged admin user" do
it "does not change @user's attributes" do
login(member_admin.user)
put :update, id: user.id, user: Fabricate.to_params(:user, username: nil, email: nil, phone: "1234", alt_phone: "4321")
expect(user.phone).not_to eq("1234")
expect(user.alt_phone).not_to eq("4321")
end
end
end
end
end
+15
View File
@@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the GlobalHelper. For example:
#
# describe GlobalHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
describe GlobalHelper do
pending "add some examples to (or delete) #{__FILE__}"
end
+7
View File
@@ -3,6 +3,7 @@ ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'capybara/rails'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
@@ -68,3 +69,9 @@ RSpec.configure do |config|
# Controllers must render the content of the view
config.render_views
end
RSpec.shared_context 'stub browser locale' do
def set_browser_locale(locale)
ApplicationController.any_instance.stub(:extract_locale_from_accept_language_header).and_return(locale)
end
end
@@ -0,0 +1,5 @@
require 'spec_helper'
describe "global/switch_lang.html.haml" do
pending "add some examples to (or delete) #{__FILE__}"
end
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

+257
View File
@@ -0,0 +1,257 @@
.flag {
width: 16px;
height: 11px;
background:url('/assets/flags.png') no-repeat
}
.flag.flag-ad {background-position: -16px 0}
.flag.flag-ae {background-position: -32px 0}
.flag.flag-af {background-position: -48px 0}
.flag.flag-ag {background-position: -64px 0}
.flag.flag-ai {background-position: -80px 0}
.flag.flag-al {background-position: -96px 0}
.flag.flag-am {background-position: -112px 0}
.flag.flag-an {background-position: -128px 0}
.flag.flag-ao {background-position: -144px 0}
.flag.flag-ar {background-position: -160px 0}
.flag.flag-as {background-position: -176px 0}
.flag.flag-at {background-position: -192px 0}
.flag.flag-au {background-position: -208px 0}
.flag.flag-aw {background-position: -224px 0}
.flag.flag-az {background-position: -240px 0}
.flag.flag-ba {background-position: 0 -11px}
.flag.flag-bb {background-position: -16px -11px}
.flag.flag-bd {background-position: -32px -11px}
.flag.flag-be {background-position: -48px -11px}
.flag.flag-bf {background-position: -64px -11px}
.flag.flag-bg {background-position: -80px -11px}
.flag.flag-bh {background-position: -96px -11px}
.flag.flag-bi {background-position: -112px -11px}
.flag.flag-bj {background-position: -128px -11px}
.flag.flag-bm {background-position: -144px -11px}
.flag.flag-bn {background-position: -160px -11px}
.flag.flag-bo {background-position: -176px -11px}
.flag.flag-br {background-position: -192px -11px}
.flag.flag-bs {background-position: -208px -11px}
.flag.flag-bt {background-position: -224px -11px}
.flag.flag-bv {background-position: -240px -11px}
.flag.flag-bw {background-position: 0 -22px}
.flag.flag-by {background-position: -16px -22px}
.flag.flag-bz {background-position: -32px -22px}
.flag.flag-ca {background-position: -48px -22px}
.flag.flag-catalonia {background-position: -64px -22px}
.flag.flag-cd {background-position: -80px -22px}
.flag.flag-cf {background-position: -96px -22px}
.flag.flag-cg {background-position: -112px -22px}
.flag.flag-ch {background-position: -128px -22px}
.flag.flag-ci {background-position: -144px -22px}
.flag.flag-ck {background-position: -160px -22px}
.flag.flag-cl {background-position: -176px -22px}
.flag.flag-cm {background-position: -192px -22px}
.flag.flag-cn {background-position: -208px -22px}
.flag.flag-co {background-position: -224px -22px}
.flag.flag-cr {background-position: -240px -22px}
.flag.flag-cu {background-position: 0 -33px}
.flag.flag-cv {background-position: -16px -33px}
.flag.flag-cw {background-position: -32px -33px}
.flag.flag-cy {background-position: -48px -33px}
.flag.flag-cz {background-position: -64px -33px}
.flag.flag-de {background-position: -80px -33px}
.flag.flag-dj {background-position: -96px -33px}
.flag.flag-dk {background-position: -112px -33px}
.flag.flag-dm {background-position: -128px -33px}
.flag.flag-do {background-position: -144px -33px}
.flag.flag-dz {background-position: -160px -33px}
.flag.flag-ec {background-position: -176px -33px}
.flag.flag-ee {background-position: -192px -33px}
.flag.flag-eg {background-position: -208px -33px}
.flag.flag-eh {background-position: -224px -33px}
.flag.flag-england {background-position: -240px -33px}
.flag.flag-er {background-position: 0 -44px}
.flag.flag-es {background-position: -16px -44px}
.flag.flag-et {background-position: -32px -44px}
.flag.flag-eu {background-position: -48px -44px}
.flag.flag-fi {background-position: -64px -44px}
.flag.flag-fj {background-position: -80px -44px}
.flag.flag-fk {background-position: -96px -44px}
.flag.flag-fm {background-position: -112px -44px}
.flag.flag-fo {background-position: -128px -44px}
.flag.flag-fr {background-position: -144px -44px}
.flag.flag-ga {background-position: -160px -44px}
.flag.flag-gb {background-position: -176px -44px}
.flag.flag-gd {background-position: -192px -44px}
.flag.flag-ge {background-position: -208px -44px}
.flag.flag-gf {background-position: -224px -44px}
.flag.flag-gg {background-position: -240px -44px}
.flag.flag-gh {background-position: 0 -55px}
.flag.flag-gi {background-position: -16px -55px}
.flag.flag-gl {background-position: -32px -55px}
.flag.flag-gm {background-position: -48px -55px}
.flag.flag-gn {background-position: -64px -55px}
.flag.flag-gp {background-position: -80px -55px}
.flag.flag-gq {background-position: -96px -55px}
.flag.flag-gr {background-position: -112px -55px}
.flag.flag-gs {background-position: -128px -55px}
.flag.flag-gt {background-position: -144px -55px}
.flag.flag-gu {background-position: -160px -55px}
.flag.flag-gw {background-position: -176px -55px}
.flag.flag-gy {background-position: -192px -55px}
.flag.flag-hk {background-position: -208px -55px}
.flag.flag-hm {background-position: -224px -55px}
.flag.flag-hn {background-position: -240px -55px}
.flag.flag-hr {background-position: 0 -66px}
.flag.flag-ht {background-position: -16px -66px}
.flag.flag-hu {background-position: -32px -66px}
.flag.flag-ic {background-position: -48px -66px}
.flag.flag-id {background-position: -64px -66px}
.flag.flag-ie {background-position: -80px -66px}
.flag.flag-il {background-position: -96px -66px}
.flag.flag-im {background-position: -112px -66px}
.flag.flag-in {background-position: -128px -66px}
.flag.flag-io {background-position: -144px -66px}
.flag.flag-iq {background-position: -160px -66px}
.flag.flag-ir {background-position: -176px -66px}
.flag.flag-is {background-position: -192px -66px}
.flag.flag-it {background-position: -208px -66px}
.flag.flag-je {background-position: -224px -66px}
.flag.flag-jm {background-position: -240px -66px}
.flag.flag-jo {background-position: 0 -77px}
.flag.flag-jp {background-position: -16px -77px}
.flag.flag-ke {background-position: -32px -77px}
.flag.flag-kg {background-position: -48px -77px}
.flag.flag-kh {background-position: -64px -77px}
.flag.flag-ki {background-position: -80px -77px}
.flag.flag-km {background-position: -96px -77px}
.flag.flag-kn {background-position: -112px -77px}
.flag.flag-kp {background-position: -128px -77px}
.flag.flag-kr {background-position: -144px -77px}
.flag.flag-kurdistan {background-position: -160px -77px}
.flag.flag-kw {background-position: -176px -77px}
.flag.flag-ky {background-position: -192px -77px}
.flag.flag-kz {background-position: -208px -77px}
.flag.flag-la {background-position: -224px -77px}
.flag.flag-lb {background-position: -240px -77px}
.flag.flag-lc {background-position: 0 -88px}
.flag.flag-li {background-position: -16px -88px}
.flag.flag-lk {background-position: -32px -88px}
.flag.flag-lr {background-position: -48px -88px}
.flag.flag-ls {background-position: -64px -88px}
.flag.flag-lt {background-position: -80px -88px}
.flag.flag-lu {background-position: -96px -88px}
.flag.flag-lv {background-position: -112px -88px}
.flag.flag-ly {background-position: -128px -88px}
.flag.flag-ma {background-position: -144px -88px}
.flag.flag-mc {background-position: -160px -88px}
.flag.flag-md {background-position: -176px -88px}
.flag.flag-me {background-position: -192px -88px}
.flag.flag-mg {background-position: -208px -88px}
.flag.flag-mh {background-position: -224px -88px}
.flag.flag-mk {background-position: -240px -88px}
.flag.flag-ml {background-position: 0 -99px}
.flag.flag-mm {background-position: -16px -99px}
.flag.flag-mn {background-position: -32px -99px}
.flag.flag-mo {background-position: -48px -99px}
.flag.flag-mp {background-position: -64px -99px}
.flag.flag-mq {background-position: -80px -99px}
.flag.flag-mr {background-position: -96px -99px}
.flag.flag-ms {background-position: -112px -99px}
.flag.flag-mt {background-position: -128px -99px}
.flag.flag-mu {background-position: -144px -99px}
.flag.flag-mv {background-position: -160px -99px}
.flag.flag-mw {background-position: -176px -99px}
.flag.flag-mx {background-position: -192px -99px}
.flag.flag-my {background-position: -208px -99px}
.flag.flag-mz {background-position: -224px -99px}
.flag.flag-na {background-position: -240px -99px}
.flag.flag-nc {background-position: 0 -110px}
.flag.flag-ne {background-position: -16px -110px}
.flag.flag-nf {background-position: -32px -110px}
.flag.flag-ng {background-position: -48px -110px}
.flag.flag-ni {background-position: -64px -110px}
.flag.flag-nl {background-position: -80px -110px}
.flag.flag-no {background-position: -96px -110px}
.flag.flag-np {background-position: -112px -110px}
.flag.flag-nr {background-position: -128px -110px}
.flag.flag-nu {background-position: -144px -110px}
.flag.flag-nz {background-position: -160px -110px}
.flag.flag-om {background-position: -176px -110px}
.flag.flag-pa {background-position: -192px -110px}
.flag.flag-pe {background-position: -208px -110px}
.flag.flag-pf {background-position: -224px -110px}
.flag.flag-pg {background-position: -240px -110px}
.flag.flag-ph {background-position: 0 -121px}
.flag.flag-pk {background-position: -16px -121px}
.flag.flag-pl {background-position: -32px -121px}
.flag.flag-pm {background-position: -48px -121px}
.flag.flag-pn {background-position: -64px -121px}
.flag.flag-pr {background-position: -80px -121px}
.flag.flag-ps {background-position: -96px -121px}
.flag.flag-pt {background-position: -112px -121px}
.flag.flag-pw {background-position: -128px -121px}
.flag.flag-py {background-position: -144px -121px}
.flag.flag-qa {background-position: -160px -121px}
.flag.flag-re {background-position: -176px -121px}
.flag.flag-ro {background-position: -192px -121px}
.flag.flag-rs {background-position: -208px -121px}
.flag.flag-ru {background-position: -224px -121px}
.flag.flag-rw {background-position: -240px -121px}
.flag.flag-sa {background-position: 0 -132px}
.flag.flag-sb {background-position: -16px -132px}
.flag.flag-sc {background-position: -32px -132px}
.flag.flag-scotland {background-position: -48px -132px}
.flag.flag-sd {background-position: -64px -132px}
.flag.flag-se {background-position: -80px -132px}
.flag.flag-sg {background-position: -96px -132px}
.flag.flag-sh {background-position: -112px -132px}
.flag.flag-si {background-position: -128px -132px}
.flag.flag-sk {background-position: -144px -132px}
.flag.flag-sl {background-position: -160px -132px}
.flag.flag-sm {background-position: -176px -132px}
.flag.flag-sn {background-position: -192px -132px}
.flag.flag-so {background-position: -208px -132px}
.flag.flag-somaliland {background-position: -224px -132px}
.flag.flag-sr {background-position: -240px -132px}
.flag.flag-ss {background-position: 0 -143px}
.flag.flag-st {background-position: -16px -143px}
.flag.flag-sv {background-position: -32px -143px}
.flag.flag-sx {background-position: -48px -143px}
.flag.flag-sy {background-position: -64px -143px}
.flag.flag-sz {background-position: -80px -143px}
.flag.flag-tc {background-position: -96px -143px}
.flag.flag-td {background-position: -112px -143px}
.flag.flag-tf {background-position: -128px -143px}
.flag.flag-tg {background-position: -144px -143px}
.flag.flag-th {background-position: -160px -143px}
.flag.flag-tj {background-position: -176px -143px}
.flag.flag-tk {background-position: -192px -143px}
.flag.flag-tl {background-position: -208px -143px}
.flag.flag-tm {background-position: -224px -143px}
.flag.flag-tn {background-position: -240px -143px}
.flag.flag-to {background-position: 0 -154px}
.flag.flag-tr {background-position: -16px -154px}
.flag.flag-tt {background-position: -32px -154px}
.flag.flag-tv {background-position: -48px -154px}
.flag.flag-tw {background-position: -64px -154px}
.flag.flag-tz {background-position: -80px -154px}
.flag.flag-ua {background-position: -96px -154px}
.flag.flag-ug {background-position: -112px -154px}
.flag.flag-um {background-position: -128px -154px}
.flag.flag-us {background-position: -144px -154px}
.flag.flag-uy {background-position: -160px -154px}
.flag.flag-uz {background-position: -176px -154px}
.flag.flag-va {background-position: -192px -154px}
.flag.flag-vc {background-position: -208px -154px}
.flag.flag-ve {background-position: -224px -154px}
.flag.flag-vg {background-position: -240px -154px}
.flag.flag-vi {background-position: 0 -165px}
.flag.flag-vn {background-position: -16px -165px}
.flag.flag-vu {background-position: -32px -165px}
.flag.flag-wales {background-position: -48px -165px}
.flag.flag-wf {background-position: -64px -165px}
.flag.flag-ws {background-position: -80px -165px}
.flag.flag-ye {background-position: -96px -165px}
.flag.flag-yt {background-position: -112px -165px}
.flag.flag-za {background-position: -128px -165px}
.flag.flag-zanzibar {background-position: -144px -165px}
.flag.flag-zm {background-position: -160px -165px}
.flag.flag-zw {background-position: -176px -165px}