Commit bf848e13595558651e27d56832b3b247d946c047
Exists in
master
and in
28 other branches
Merge branch 'refactoring' into selenium
Conflicts: plugins/mezuro/public/javascripts/project_content.js
Showing
308 changed files
with
76354 additions
and
69184 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 308 files displayed.
AUTHORS
... | ... | @@ -6,45 +6,144 @@ noosfero, that's not a problem). |
6 | 6 | Developers |
7 | 7 | ========== |
8 | 8 | |
9 | +Alan Freihof Tygel <alantygel@gmail.com> | |
10 | +Alessandro Palmeira <alessandro.palmeira@gmail.com> | |
11 | +Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> | |
12 | +Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> | |
13 | +Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com> | |
14 | +Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> | |
15 | +Alessandro Palmeira + Carlos Morais <alessandro.palmeira@gmail.com> | |
16 | +Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com> | |
17 | +Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com> | |
18 | +Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | |
19 | +Alessandro Palmeira + Diego Araújo + Pedro Leal + João M. M. da Silva <diegoamc90@gmail.com> | |
20 | +Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com> | |
21 | +Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com> | |
22 | +Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com> | |
23 | +Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com> | |
24 | +Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> | |
25 | +Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> | |
26 | +Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> | |
9 | 27 | Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> |
10 | 28 | Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> |
11 | 29 | Antonio Terceiro <terceiro@colivre.coop.br> |
12 | 30 | Aurelio A. Heckert <aurelio@colivre.coop.br> |
13 | 31 | Braulio Bhavamitra <brauliobo@gmail.com> |
14 | 32 | Bráulio Bhavamitra <brauliobo@gmail.com> |
33 | +Caio <caio.csalgado@gmail.com> | |
34 | +Caio + Diego + Pedro + João <caio.csalgado@gmail.com> | |
35 | +Caio, Pedro <caio.csalgado@gmail.com> | |
36 | +Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com> | |
37 | +Caio Salgado <caio.csalgado@gmail.com> | |
38 | +Caio Salgado + Carlos Morais + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | |
39 | +Caio Salgado + Diego Araujo <caio.csalgado@gmail.com> | |
40 | +Caio Salgado + Diego Araújo <caio.csalgado@gmail.com> | |
41 | +Caio Salgado + Diego Araújo <diegoamc90@gmail.com> | |
42 | +Caio Salgado + Diego Araújo + Jefferson Fernandes <caio.csalgado@gmail.com> | |
43 | +Caio Salgado + Diego Araújo + João M. M. da Silva <caio.csalgado@gmail.com> | |
44 | +Caio Salgado + Diego Araújo + Pedro Leal <caio.csalgado@gmail.com> | |
45 | +Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | |
46 | +Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> | |
47 | +Caio Salgado + Jefferson Fernandes <caio.csalgado@gmail.com> | |
48 | +Caio Salgado + Jefferson Fernandes <jeffs.fernandes@gmail.com> | |
49 | +Caio Salgado + Rafael Manzo <caio.csalgado@gmail.com> | |
50 | +Caio Salgado + Renan Teruo <caio.csalgado@gmail.com> | |
51 | +Caio Salgado + Renan Teruo <caio.salgado@gmail.com> | |
52 | +Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com> | |
53 | +Caio Salgado + Renan Teruo <renanteruoc@gmail.com> | |
15 | 54 | Caio SBA <caio@colivre.coop.br> |
16 | 55 | Carlos Morais <carlos88morais@gmail.com> |
17 | 56 | Carlos Morais + Diego Araújo <diegoamc90@gmail.com> |
57 | +Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> | |
18 | 58 | Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com> |
59 | +Carlos Morais + Pedro Leal <carlos88morais@gmail.com> | |
19 | 60 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> |
20 | 61 | Daniel Cunha <daniel@colivre.coop.br> |
62 | +diegoamc <diegoamc90@gmail.com> | |
63 | +Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> | |
64 | +Diego Araujo + Caio Salgado <diegoamc90@gmail.com> | |
21 | 65 | Diego Araújo <diegoamc90@gmail.com> |
66 | +Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com> | |
67 | +Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com> | |
68 | +Diego Araújo + João Machini <diegoamc90@gmail.com> | |
69 | +Diego Araújo + João Machini <digoamc90@gmail.com> | |
22 | 70 | Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> |
71 | +Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com> | |
72 | +Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com> | |
73 | +Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com> | |
74 | +Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | |
75 | +Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> | |
76 | +Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com> | |
77 | +Diego Araújo + Renan Teruo <diegoamc90@gmail.com> | |
78 | +Diego + Jefferson <diegoamc90@gmail.com> | |
79 | +Diego Martinez <diegoamc90@gmail.com> | |
80 | +Diego + Renan <renanteruoc@gmail.com> | |
23 | 81 | Fernanda Lopes <nanda.listas+psl@gmail.com> |
24 | 82 | Grazieno Pellegrino <grazieno@gmail.com> |
25 | 83 | Isaac Canan <isaac@intelletto.com.br> |
26 | 84 | Italo Valcy <italo@dcc.ufba.br> |
85 | +Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> | |
86 | +Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> | |
87 | +Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> | |
27 | 88 | João da Silva <jaodsilv@linux.ime.usp.br> |
89 | +João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> | |
90 | +João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br> | |
91 | +João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br> | |
92 | +João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | |
93 | +João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br> | |
94 | +João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | |
95 | +João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br> | |
28 | 96 | João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br> |
29 | 97 | João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com> |
30 | 98 | João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br> |
99 | +João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br> | |
100 | +João M. M. da Silva <jaodsilv@linux.ime.usp.br> | |
101 | +Joao M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | |
102 | +João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | |
103 | +João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br> | |
31 | 104 | João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br> |
105 | +João M. M. da Silva + Pedro Leal <jaodsilv@linux.ime.usp.br> | |
106 | +João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br> | |
107 | +João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> | |
108 | +João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> | |
109 | +João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br> | |
110 | +João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br> | |
111 | +Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | |
112 | +João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br> | |
113 | +João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> | |
114 | +João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> | |
32 | 115 | Joenio Costa <joenio@colivre.coop.br> |
33 | 116 | Josef Spillner <josef.spillner@tu-dresden.de> |
34 | 117 | Keilla Menezes <keilla@colivre.coop.br> |
35 | 118 | Larissa Reis <larissa@colivre.coop.br> |
36 | 119 | Larissa Reis <reiss.larissa@gmail.com> |
37 | 120 | Leandro Nunes dos Santos <leandronunes@gmail.com> |
121 | +Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> | |
38 | 122 | LinguÁgil 2010 <linguagil.bahia@gmail.com> |
123 | +Luis David Aguilar Carlos <ludwig9003@gmail.com> | |
39 | 124 | Martín Olivera <molivera@solar.org.ar> |
40 | 125 | Moises Machado <moises@colivre.coop.br> |
41 | 126 | Nanda Lopes <nanda.listas+psl@gmail.com> |
127 | +Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> | |
42 | 128 | Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> |
129 | +Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org> | |
130 | +Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org> | |
43 | 131 | Paulo Meirelles <paulo@softwarelivre.org> |
44 | 132 | Rafael Gomes <rafaelgomes@techfree.com.br> |
133 | +Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com> | |
45 | 134 | Rafael Martins <rmmartins@gmail.com> |
135 | +Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com> | |
136 | +Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com> | |
137 | +Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com> | |
138 | +Rafael Reggiani Manzo <rr.manzo@gmail.com> | |
46 | 139 | Raphaël Rousseau <raph@r4f.org> |
47 | 140 | Raquel Lira <raquel.lira@gmail.com> |
141 | +Renan Teruo + Caio Salgado <renanteruoc@gmail.com> | |
142 | +Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> | |
143 | +Renan Teruo + Diego Araujo <renanteruoc@gmail.com> | |
144 | +Renan Teruo + Diego Araújo <renanteruoc@gmail.com> | |
145 | +Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> | |
146 | +Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> | |
48 | 147 | Rodrigo Souto <rodrigo@colivre.coop.br> |
49 | 148 | Ronny Kursawe <kursawe.ronny@googlemail.com> |
50 | 149 | Samuel R. C. Vale <srcvale@holoscopio.com> | ... | ... |
Gemfile
1 | 1 | source :rubygems |
2 | -gem 'cucumber', '0.4.0' | |
3 | -gem 'webrat', '0.5.1' | |
4 | -gem 'rspec', '1.2.9' | |
5 | -gem 'rspec-rails', '1.2.9' | |
6 | -gem 'Selenium', '>= 1.1.14' | |
7 | -gem 'selenium-client', '>= 1.2.17' | |
8 | -gem 'database_cleaner' | |
2 | + | |
9 | 3 | gem 'exception_notification', '1.0.20090728' |
10 | 4 | gem 'system_timer' |
11 | 5 | |
6 | +group :test do | |
7 | + gem 'rspec', '1.2.9' | |
8 | + gem 'rspec-rails', '1.2.9' | |
9 | +end | |
10 | + | |
11 | +group :cucumber do | |
12 | + gem 'rake', '0.8.7' | |
13 | + gem 'cucumber-rails', '0.3.2' | |
14 | + gem 'capybara', '1.1.1' | |
15 | + gem 'cucumber', '1.1.0' | |
16 | + gem 'database_cleaner' | |
17 | +end | |
18 | + | |
12 | 19 | def program(name) |
13 | 20 | unless system("which #{name} > /dev/null") |
14 | 21 | puts "W: Program #{name} is needed, but was not found in your PATH" | ... | ... |
Gemfile.lock
1 | 1 | GEM |
2 | 2 | remote: http://rubygems.org/ |
3 | 3 | specs: |
4 | - Selenium (1.1.14) | |
5 | - builder (3.0.0) | |
6 | - cucumber (0.4.0) | |
4 | + builder (3.1.4) | |
5 | + capybara (1.1.1) | |
6 | + mime-types (>= 1.16) | |
7 | + nokogiri (>= 1.3.3) | |
8 | + rack (>= 1.0.0) | |
9 | + rack-test (>= 0.5.4) | |
10 | + selenium-webdriver (~> 2.0) | |
11 | + xpath (~> 0.1.4) | |
12 | + childprocess (0.3.6) | |
13 | + ffi (~> 1.0, >= 1.0.6) | |
14 | + cucumber (1.1.0) | |
7 | 15 | builder (>= 2.1.2) |
8 | 16 | diff-lcs (>= 1.1.2) |
9 | - polyglot (>= 0.2.9) | |
10 | - term-ansicolor (>= 1.0.3) | |
11 | - treetop (>= 1.4.2) | |
12 | - database_cleaner (0.7.0) | |
17 | + gherkin (~> 2.5.0) | |
18 | + json (>= 1.4.6) | |
19 | + term-ansicolor (>= 1.0.6) | |
20 | + cucumber-rails (0.3.2) | |
21 | + cucumber (>= 0.8.0) | |
22 | + database_cleaner (0.9.1) | |
13 | 23 | diff-lcs (1.1.3) |
14 | 24 | exception_notification (1.0.20090728) |
15 | - nokogiri (1.5.0) | |
16 | - polyglot (0.3.3) | |
17 | - rack (1.3.5) | |
25 | + ffi (1.2.0) | |
26 | + gherkin (2.5.4) | |
27 | + json (>= 1.4.6) | |
28 | + json (1.7.5) | |
29 | + libwebsocket (0.1.6.1) | |
30 | + websocket | |
31 | + mime-types (1.19) | |
32 | + multi_json (1.3.7) | |
33 | + nokogiri (1.5.5) | |
34 | + rack (1.1.0) | |
35 | + rack-test (0.6.2) | |
36 | + rack (>= 1.0) | |
37 | + rake (0.8.7) | |
18 | 38 | rspec (1.2.9) |
19 | 39 | rspec-rails (1.2.9) |
20 | 40 | rack (>= 1.0.0) |
21 | 41 | rspec (>= 1.2.9) |
22 | - selenium-client (1.2.18) | |
42 | + rubyzip (0.9.9) | |
43 | + selenium-webdriver (2.26.0) | |
44 | + childprocess (>= 0.2.5) | |
45 | + libwebsocket (~> 0.1.3) | |
46 | + multi_json (~> 1.0) | |
47 | + rubyzip | |
23 | 48 | system_timer (1.2.4) |
24 | 49 | term-ansicolor (1.0.7) |
25 | - treetop (1.4.10) | |
26 | - polyglot | |
27 | - polyglot (>= 0.3.1) | |
28 | - webrat (0.5.1) | |
29 | - nokogiri (>= 1.2.0) | |
30 | - rack (>= 1.0) | |
50 | + websocket (1.0.4) | |
51 | + xpath (0.1.4) | |
52 | + nokogiri (~> 1.3) | |
31 | 53 | |
32 | 54 | PLATFORMS |
33 | 55 | ruby |
34 | 56 | |
35 | 57 | DEPENDENCIES |
36 | - Selenium (>= 1.1.14) | |
37 | - cucumber (= 0.4.0) | |
58 | + capybara (= 1.1.1) | |
59 | + cucumber (= 1.1.0) | |
60 | + cucumber-rails (= 0.3.2) | |
38 | 61 | database_cleaner |
39 | 62 | exception_notification (= 1.0.20090728) |
63 | + rake (= 0.8.7) | |
40 | 64 | rspec (= 1.2.9) |
41 | 65 | rspec-rails (= 1.2.9) |
42 | - selenium-client (>= 1.2.17) | |
43 | 66 | system_timer |
44 | - webrat (= 0.5.1) | ... | ... |
HACKING
1 | 1 | = Noosfero instructions for developers |
2 | 2 | |
3 | -This document provides useful information to those who want to help with | |
4 | -Noosfero development. | |
3 | +== A work about your the development platform | |
5 | 4 | |
6 | -== Requirements for development | |
5 | +These instructions are tested and known to work on Debian stable, which is the | |
6 | +system that the Noosfero core developers use to work on Noosfero. | |
7 | 7 | |
8 | -First, install all requirements listed in INSTALL. Note that you do not need to | |
9 | -follow all the steps described there, you only need to install the packages | |
10 | -listed in the "Requirements" section. | |
8 | +If you want to use another OS, read "Instructions for other systems" below. | |
11 | 9 | |
12 | -After installing the requirements listed in INSTALL, you need to install some | |
13 | -packages be able to run Noosfero tests. On Debian GNU/Linux and Debian-based | |
14 | -systems, you install them with the following command: | |
10 | +== Instructions for Debian stable | |
15 | 11 | |
16 | - # apt-get install libtidy-ruby libhpricot-ruby libmocha-ruby imagemagick po4a xvfb libxml2-dev libxslt-dev | |
12 | +Download the source code: | |
17 | 13 | |
18 | -On other systems, they may or may not be available through your regular package | |
19 | -management system. Below are the links to their homepages. | |
14 | + $ git clone git://gitorious.org/noosfero/noosfero.git | |
15 | + $ cd noosfero | |
20 | 16 | |
21 | -* Mocha: http://mocha.rubyforge.org/ | |
22 | -* Tidy: http://tidy.sourceforge.net/ | |
23 | -* Hpricot: http://github.com/whymirror/hpricot | |
24 | -* Imagemagick: http://wwwimagemagick.org/ | |
25 | -* po4a: http://po4a.alioth.debian.org/ | |
26 | -* xvfb: http://packages.debian.org/lenny/xvfb | |
27 | -* Libxml2: http://xmlsoft.org/ | |
28 | -* Libxslt: http://xmlsoft.org/xslt | |
17 | +Run the quick start script: | |
29 | 18 | |
30 | -== Boostraping a development/test environment | |
19 | + $ ./script/quick-start | |
31 | 20 | |
32 | -You can copy and paste the commands below into a terminal (please review the | |
33 | -commands and make sure you understand what you are doing): | |
21 | +Now you can execute the development server with: | |
34 | 22 | |
35 | - # checkout the code from repository | |
36 | - git clone git://gitorious.org/noosfero/noosfero.git | |
37 | - # enter the directory | |
38 | - cd noosfero | |
39 | - # copy a sample config file | |
40 | - cp config/database.yml.sqlite3 config/database.yml | |
41 | - # create tmp directory if it doesn't exist | |
42 | - mkdir tmp | |
43 | - # start Solr | |
44 | - rake solr:start | |
45 | - # create the development database | |
46 | - rake db:schema:load | |
47 | - # run pending migrations | |
48 | - rake db:migrate | |
49 | - # compile translations: | |
50 | - rake makemo | |
51 | - # create some test data: | |
52 | - ./script/sample-data | |
53 | - # install latest requirements for running tests | |
54 | - RAILS_ENV=cucumber rake gems:install | |
55 | - RAILS_ENV=test rake gems:install | |
56 | - # run the automated test suite to make sure your environment is sane: | |
57 | - rake test | |
23 | + $ ./script/development | |
58 | 24 | |
59 | -You should now be ready to go. Issue the following command to start the Rails | |
60 | -development server: | |
25 | +You will be able to access Noosfero at http://localhost:3000/ | |
61 | 26 | |
62 | - ./script/server | |
27 | +If you want to use a different port than 3000, pass `-p <PORT>` to | |
28 | +./script/development | |
63 | 29 | |
64 | -The server will be available at http://localhost:3000/ . If you want to use | |
65 | -another port than 3000, you can use the -p option of ./script/server: | |
30 | +== Instructions for other systems | |
66 | 31 | |
67 | - ./script/server -p 9999 | |
32 | +On other OS, you have 2 options: | |
68 | 33 | |
69 | -The above command makes the server available at http://localhost:9999/ | |
34 | +1) using a chroot or a VM with Debian stable (easier) | |
70 | 35 | |
71 | -The sample-data data scripts creates two administrator users with login "ze" and | |
72 | -password "test" and login "adminuser" and password "admin". | |
36 | +Use a chroot (http://wiki.debian.org/Schroot) or a Virtual Machine (e.g. with | |
37 | +VirtualBox) with a Debian stable system and follow the instructions above for | |
38 | +Debian stable. | |
73 | 39 | |
74 | -Note that some operations, like generating image thumbnails, sending e-mails, | |
75 | -etc, are done in background in the context of a service independent from the | |
76 | -Rails application server. To have those tasks performed in a development | |
77 | -environment, you must run the delayed_job server like this: | |
40 | +2) Installing dependencies on other OS (harder) | |
78 | 41 | |
79 | - ./script/delayed_job run | |
42 | +If you want to setup a development environment in another OS, you can create a | |
43 | +file under script/install-dependencies/, called <OS>-<CODENAME>.sh, which | |
44 | +installed the dependencies for your system. With this script in place, | |
45 | +./script/quick-start will call it at the point of installing the required | |
46 | +packages for Noosfero development. | |
80 | 47 | |
81 | -This will block your terminal. To stop the delayed_job server, hit Control-C. | |
48 | +You can check script/install-dependencies/debian-squeeze.sh to have an idea of | |
49 | +what kind of stuff that script has to do. | |
82 | 50 | |
83 | -== Enabling exceptions notification | |
84 | - | |
85 | -By default, exception notifications are disabled in development environment. If | |
86 | -you want to enable it then you need to change some files: | |
87 | - | |
88 | -1) Add in config/environments/development.rb: | |
89 | - config.action_controller.consider_all_requests_local = false | |
90 | - | |
91 | -2) Add in app/controller/application.rb: | |
92 | - local_addresses.clear | |
93 | - | |
94 | -3) Add in config/noosfero.yml at development section: | |
95 | - exception_recipients: [admin@example.com] | |
96 | - | |
97 | -== Releasing and building Debian package | |
98 | - | |
99 | -See RELEASING file. | |
51 | +If you write such script for your own OS, *please* share it with us at the | |
52 | +development mailing list so that we can include it in the official repository. | |
53 | +This way other people using the same OS will have to put less effort to develop | |
54 | +Noosfero. | ... | ... |
INSTALL
1 | -= Noosfero installation instructions | |
1 | += Noosfero installation instructions from source for production environments | |
2 | 2 | |
3 | -Noosfero is written in Ruby with the "Rails framework":http://www.rubyonrails.org, | |
4 | -so the process of setting it up is pretty similar to other Rails applications. | |
3 | +The instructions below can be used for setting up a Noosfero production | |
4 | +environment from the Noosfero sources. | |
5 | 5 | |
6 | -Below we have the instructions for installing Noosfero dependencies and setting | |
7 | -up a production environment. If you have problems with the setup, please feel | |
8 | -free to ask questions in the development mailing list. | |
6 | +Before you start installing Noosfero manually, see the information about the | |
7 | +Noosfero Debian package at http://noosfero.org/Development/DebianPackage. Using | |
8 | +the Debian packages on a Debian stable system is the recommended method for | |
9 | +installing production environments. | |
10 | + | |
11 | +If you want to setup a development environment instead of a production one, | |
12 | +stop reading this file right now and read the file HACKING instead. | |
13 | + | |
14 | +For a complete installation guide, please see the following web page: | |
15 | +http://noosfero.org/Development/HowToInstall | |
16 | + | |
17 | +If you have problems with the setup, please feel free to ask questions in the | |
18 | +development mailing list. | |
9 | 19 | |
10 | 20 | == Requirements |
11 | 21 | |
22 | +DISCLAIMER: this installation procedure is tested with Debian stable, which is | |
23 | +currently the only recommended operating system for production usage. It is | |
24 | +possible that you can install it on other systems, and if you do so, please | |
25 | +report it on one of the Noosfero mailing lists, and please send a patch | |
26 | +updating these instructions. | |
27 | + | |
28 | +Noosfero is written in Ruby with the "Rails | |
29 | +framework":http://www.rubyonrails.org, so the process of setting it up is | |
30 | +pretty similar to other Rails applications. | |
31 | + | |
12 | 32 | You need to install some packages Noosfero depends on. On Debian GNU/Linux or |
13 | 33 | Debian-based systems, all of these packages are available through the Debian |
14 | 34 | archive. You can install them with the following command: |
... | ... | @@ -38,21 +58,9 @@ If you manage to install Noosfero successfully on other systems than Debian, |
38 | 58 | please feel free to contact the Noosfero development mailing with the |
39 | 59 | instructions for doing so, and we'll include it here. |
40 | 60 | |
41 | -=== Setting up a production environment | |
42 | - | |
43 | -DISCLAIMER: this installation procedure is tested with Debian stable, which is | |
44 | -currently the only recommended operating system for production usage. It is | |
45 | -possible that you can install it on other systems, and if you do so, please | |
46 | -report it on one of the Noosfero mailing lists, and please send a patch | |
47 | -updating these instructions. | |
48 | - | |
49 | 61 | As root user |
50 | 62 | ============ |
51 | 63 | |
52 | -NOTE: these instructions are for seting up a *production* environment. If you | |
53 | -are going to do Noosfero development, you don't need to do these steps. Stop | |
54 | -here and see the HACKING file instead. | |
55 | - | |
56 | 64 | Install memcached. On Debian: |
57 | 65 | |
58 | 66 | # apt-get install memcached |
... | ... | @@ -96,11 +104,11 @@ $ git checkout -b stable origin/stable |
96 | 104 | downloading tarball |
97 | 105 | ------------------- |
98 | 106 | |
99 | -Note: replace 0.35.0 below from the latest stable version. | |
107 | +Note: replace 0.39.0 below from the latest stable version. | |
100 | 108 | |
101 | -$ wget http://noosfero.org/pub/Development/NoosferoVersion00x35x00/noosfero-0.35.0.tar.gz | |
102 | -$ tar -zxvf noosfero-0.35.0.tar.gz | |
103 | -$ ln -s noosfero-0.35.0 current | |
109 | +$ wget http://noosfero.org/pub/Development/NoosferoVersion00x39x00/noosfero-0.39.0.tar.gz | |
110 | +$ tar -zxvf noosfero-0.39.0.tar.gz | |
111 | +$ ln -s noosfero-0.39.0 current | |
104 | 112 | $ cd current |
105 | 113 | |
106 | 114 | Copy config/solr.yml.dist to config/solr.yml. You will |
... | ... | @@ -108,7 +116,7 @@ probably not need to customize this configuration, but have a look at it. |
108 | 116 | |
109 | 117 | Create the thin configuration file: |
110 | 118 | |
111 | -$ thin -C config/thin.yml config | |
119 | +$ thin -C config/thin.yml -e production config | |
112 | 120 | |
113 | 121 | Edit config/thin.yml to suit your needs. Make sure your apache |
114 | 122 | configuration matches the thin cluster configuration, specially in respect |
... | ... | @@ -147,48 +155,7 @@ Restart postgresql: |
147 | 155 | |
148 | 156 | Noosfero needs a functional e-mail setup to work: the local mail system should |
149 | 157 | be able to deliver e-mail to the internet, either directly or through an |
150 | -external SMTP server. | |
151 | - | |
152 | -If you know mail systems well, you just need to make sure thet the local MTA, | |
153 | -listening on localhost:25, is able to deliver e-mails to the internet. Any mail | |
154 | -server will do it. | |
155 | - | |
156 | -If you are not a mail specialist, we suggest that you use the Postfix mail | |
157 | -server, since it is easy to configure and very reliable. Just follow the | |
158 | -instructions below. | |
159 | - | |
160 | -To install Postfix: | |
161 | - | |
162 | -# apt-get install postfix | |
163 | - | |
164 | -During the installation process, you will be asked a few questions. Your answer | |
165 | -to them will vary in 2 cases: | |
166 | - | |
167 | -Case 1: you can send e-mails directly to the internet. This will be the case | |
168 | -for most commercial private servers. Your answers should be: | |
169 | - | |
170 | - General type of mail configuration: Internet site | |
171 | - System mail name: the name of your domain, e.g. "mysocialnetwork.com" | |
172 | - | |
173 | -Case 2: you cannot, or don't want to, send e-mail directly to the internet. | |
174 | -This happens for example if your server is not allowed to make outbound | |
175 | -connections on port 25, or if you want to concentrate all your outbound mail | |
176 | -through a single SMTP server. Your answers in this case should be: | |
177 | - | |
178 | - General type of mail configuration: Internet with smarthost | |
179 | - System mail name: the name of your domain, e.g. "mysocialnetwork.com" | |
180 | - SMTP relay host: smtp.yourprovider.com | |
181 | - | |
182 | -Note that smtp.yourprovider.com must allow your server to deliver e-mails | |
183 | -through it. You should probably ask your servive provider about this. | |
184 | - | |
185 | -There is another possibility: if you are installing on a shared server, and | |
186 | -don't have permission to configure the local MTA, you can instruct Noosfero to | |
187 | -send e-mails directly through an external server. Please note that this should | |
188 | -be your last option, since contacting an external SMTP server directly may slow | |
189 | -down your Noosfero application server. To configure Noosfero to send e-mails | |
190 | -through an external SMTP server, follow the instructions on | |
191 | -http://noosfero.org/Development/SMTPMailSending | |
158 | +external SMTP server. Please check the documentation at the INSTALL.email file. | |
192 | 159 | |
193 | 160 | As noosfero user |
194 | 161 | ================ |
... | ... | @@ -220,19 +187,6 @@ $ ./script/dbconsole production |
220 | 187 | If it connects to your database, then everything is fine. If you got an error |
221 | 188 | message, then you have to check your database configuration. |
222 | 189 | |
223 | -Installing gem rack | |
224 | -=================== | |
225 | - | |
226 | -This gem is required if you want to run Mezuro plugin. | |
227 | - | |
228 | -Install RubyGem Rack 1.0.1. | |
229 | -Others versions may not be compatible with Noosfero: | |
230 | - | |
231 | -# gem install rack -v 1.0.1 | |
232 | - | |
233 | -As noosfero user | |
234 | -================ | |
235 | - | |
236 | 190 | Create the database structure: |
237 | 191 | |
238 | 192 | $ RAILS_ENV=production rake db:schema:load |
... | ... | @@ -245,7 +199,7 @@ Run Solr: |
245 | 199 | |
246 | 200 | $ rake solr:start |
247 | 201 | |
248 | -Now we have to create some initial data. To create your default environment | |
202 | +Now we must create some initial data. To create your default environment | |
249 | 203 | (the first one), run the command below: |
250 | 204 | |
251 | 205 | $ RAILS_ENV=production ./script/runner 'Environment.create!(:name => "My environment", :is_default => true)' |
... | ... | @@ -261,10 +215,10 @@ $ RAILS_ENV=production ./script/runner "Environment.default.domains << Domain.ne |
261 | 215 | |
262 | 216 | Add at least one user as admin of environment: |
263 | 217 | |
264 | -$ RAILS_ENV=production ./script/runner "User.create(:login => 'adminuser', :email => 'admin@example.com', :password => 'admin', :password_confirmation => 'admin', :environment => Environment.default)" | |
218 | +$ RAILS_ENV=production ./script/runner "User.create(:login => 'adminuser', :email => 'admin@example.com', :password => 'admin', :password_confirmation => 'admin', :environment => Environment.default, :activated_at => Time.new)" | |
265 | 219 | |
266 | 220 | (replace "adminuser", "admin@example.com", "admin" with the login, email |
267 | -and password of your environment admin) | |
221 | +and password of your environment administrator) | |
268 | 222 | |
269 | 223 | To start the Noosfero application servers: |
270 | 224 | |
... | ... | @@ -274,23 +228,6 @@ At this point you have a functional Noosfero installation running, the only |
274 | 228 | thing left is to configure your webserver as a reverse proxy to pass requests |
275 | 229 | to them. |
276 | 230 | |
277 | -Enabling exception notifications | |
278 | -================================ | |
279 | - | |
280 | -This is an optional step. You will need it only if you want to receive e-mail | |
281 | -notifications when some exception occurs on Noosfero. | |
282 | - | |
283 | -First, install this version of the gem. | |
284 | -Others versions may not be compatible with Noosfero: | |
285 | - | |
286 | -# gem install exception_notification -v 1.0.20090728 | |
287 | - | |
288 | -You can configure the e-mails that will receive the notifications. | |
289 | -Change the file config/noosfero.yml as the following example, replacing the | |
290 | -e-mails by real ones: | |
291 | - | |
292 | - production: | |
293 | - exception_recipients: [admin@example.com, you@example.com] | |
294 | 231 | |
295 | 232 | ================== |
296 | 233 | Apache instalation |
... | ... | @@ -384,6 +321,26 @@ Now restart your apache server (as root): |
384 | 321 | |
385 | 322 | # invoke-rc.d apache2 restart |
386 | 323 | |
324 | + | |
325 | +Enabling exception notifications | |
326 | +================================ | |
327 | + | |
328 | +This is an optional step. You will need it only if you want to receive e-mail | |
329 | +notifications when some exception occurs on Noosfero. | |
330 | + | |
331 | +First, install this version of the gem. | |
332 | +Others versions may not be compatible with Noosfero: | |
333 | + | |
334 | +# gem install exception_notification -v 1.0.20090728 | |
335 | + | |
336 | +You can configure the e-mails that will receive the notifications. | |
337 | +Change the file config/noosfero.yml as the following example, replacing the | |
338 | +e-mails by real ones: | |
339 | + | |
340 | + production: | |
341 | + exception_recipients: [admin@example.com, you@example.com] | |
342 | + | |
343 | + | |
387 | 344 | ============ |
388 | 345 | Maintainance |
389 | 346 | ============ | ... | ... |
... | ... | @@ -0,0 +1,43 @@ |
1 | += Noosfero email setup | |
2 | + | |
3 | +If you know mail systems well, you just need to make sure that the local MTA, | |
4 | +listening on localhost:25, is able to deliver e-mails to the internet. Any mail | |
5 | +server will do it. You can stop reading now. | |
6 | + | |
7 | +If you are not an email specialist, then follow the instructions below. We | |
8 | +suggest that you use the Postfix mail server, since it is easy to configure and | |
9 | +very reliable. Just follow the instructions below. | |
10 | + | |
11 | +To install Postfix: | |
12 | + | |
13 | +# apt-get install postfix | |
14 | + | |
15 | +During the installation process, you will be asked a few questions. Your answer | |
16 | +to them will vary in 2 cases: | |
17 | + | |
18 | +Case 1: you can send e-mails directly to the internet. This will be the case | |
19 | +for most commercial private servers. Your answers should be: | |
20 | + | |
21 | + General type of mail configuration: Internet site | |
22 | + System mail name: the name of your domain, e.g. "mysocialnetwork.com" | |
23 | + | |
24 | +Case 2: you cannot, or don't want to, send e-mail directly to the internet. | |
25 | +This happens for example if your server is not allowed to make outbound | |
26 | +connections on port 25, or if you want to concentrate all your outbound mail | |
27 | +through a single SMTP server. Your answers in this case should be: | |
28 | + | |
29 | + General type of mail configuration: Internet with smarthost | |
30 | + System mail name: the name of your domain, e.g. "mysocialnetwork.com" | |
31 | + SMTP relay host: smtp.yourprovider.com | |
32 | + | |
33 | +Note that smtp.yourprovider.com must allow your server to deliver e-mails | |
34 | +through it. You should probably ask your servive provider about this. | |
35 | + | |
36 | +There is another possibility: if you are installing on a shared server, and | |
37 | +don't have permission to configure the local MTA, you can instruct Noosfero to | |
38 | +send e-mails directly through an external server. Please note that this should | |
39 | +be your last option, since contacting an external SMTP server directly may slow | |
40 | +down your Noosfero application server. To configure Noosfero to send e-mails | |
41 | +through an external SMTP server, follow the instructions on | |
42 | +http://noosfero.org/Development/SMTPMailSending | |
43 | + | ... | ... |
INSTALL.varnish
... | ... | @@ -5,75 +5,67 @@ recommended. See http://www.varnish-cache.org/ for more information on Varnish. |
5 | 5 | |
6 | 6 | Varnish can be set up to use with Noosfero with the following steps: |
7 | 7 | |
8 | -1) setup Noosfero with apache according to the INSTALL file. | |
8 | +1) setup Noosfero with apache according to the INSTALL file. If you used the | |
9 | +Debian package to install noosfero, you don't need to do anything about this. | |
9 | 10 | |
10 | 11 | 2) install Varnish |
11 | 12 | |
12 | 13 | # apt-get install varnish |
13 | 14 | |
14 | -Noosfero was tested with Varnish 2.x. If you are using a Debian Lenny (and you | |
15 | -should, unless Debian already released Squeeze by now), make sure you install | |
16 | -varnish from the lenny-backports suite. | |
17 | - | |
18 | 15 | Install the RPAF apache module (or skip this step if not using apache): |
19 | 16 | |
20 | 17 | # apt-get install libapache2-mod-rpaf |
21 | 18 | |
22 | -3) Enable varnish logging: | |
19 | +3) Change Apache to listen on port 8080 instead of 80 | |
23 | 20 | |
24 | -3a) Edit /etc/default/varnishncsa and uncomment the line that contains: | |
21 | +3a) Edit /etc/apache2/ports.conf, and: | |
25 | 22 | |
26 | -VARNISHNCSA_ENABLED=1 | |
23 | + * change 'NameVirtualHost *:80' to 'NameVirtualHost *:8080' | |
24 | + * change 'Listen 80' to 'Listen 127.0.0.1:8080' | |
27 | 25 | |
28 | -The varnish log will be written to /var/log/varnish/varnishncsa.log in an | |
29 | -apache-compatible format. You should change your statistics generation software | |
30 | -(e.g. awstats) to use that instead of apache logs. | |
26 | +3b) Edit /etc/apache2/sites-enabled/*, and change '<VirtualHost *:80>' to | |
27 | +'<VirtualHost *:8080>' | |
31 | 28 | |
32 | -3b) Restart Varnish Logging service | |
29 | +3c) Restart apache | |
33 | 30 | |
34 | - # invoke-rc.d varnishncsa start | |
31 | + # invoke-rc.d apache2 restart | |
35 | 32 | |
36 | -4) Change Apache to listen on port 8080 instead of 80 | |
33 | +4) Varnish configuration | |
37 | 34 | |
38 | -4a) Edit /etc/apache2/ports.conf, and: | |
35 | +4a) Edit /etc/default/varnish | |
39 | 36 | |
40 | - * change 'Listen 80' to 'Listen 127.0.0.1:8080' | |
41 | - * change 'NameVirtualHost *:80' to 'NameVirtualHost *:8080' | |
37 | + * change the line that says "START=no" to say "START=yes" | |
38 | + * change '-a :6081' to '-a :80' | |
42 | 39 | |
43 | -4b) Edit /etc/apache2/sites-enabled/*, and change '<VirtualHost *:80>' to '<VirtualHost *:8080>' | |
40 | +4b) Edit /etc/varnish/default.vcl and add the following lines at the end: | |
44 | 41 | |
45 | -4c) Restart apache | |
42 | + include "/etc/noosfero/varnish-noosfero.vcl"; | |
43 | + include "/etc/noosfero/varnish-accept-language.vcl"; | |
46 | 44 | |
47 | - # invoke-rc.d apache2 restart | |
45 | +On manual installations, change "/etc/noosfero/*" to | |
46 | +"{Rails.root}/etc/noosfero/*" | |
48 | 47 | |
49 | -5) Change Varnish to listen on port 80 | |
48 | +NOTE: it is very important that the *.vcl files are included in that order, | |
49 | +i.e. *first* include "varnish-noosfero.vcl", and *after* | |
50 | +"noosfero-accept-language.cvl". | |
50 | 51 | |
51 | -5a) Edit /etc/default/varnish and change '-a :6081' to '-a :80' | |
52 | - | |
53 | -5b) Restart Varnish | |
52 | +4c) Restart Varnish | |
54 | 53 | |
55 | 54 | # invoke-rc.d varnish restart |
56 | 55 | |
57 | -6) Configure varnish to fit noosfero | |
58 | -(assuming Noosfero is installed in /var/lib/noosfero) | |
59 | - | |
60 | -6a) Configure noosfero to do specific routines to varnish | |
61 | - | |
62 | -Add the following line to your /etc/varnish/default.vcl file: | |
56 | +5) Enable varnish logging: | |
63 | 57 | |
64 | - include "/var/lib/noosfero/etc/noosfero/varnish-noosfero.vcl"; | |
58 | +5a) Edit /etc/default/varnishncsa and uncomment the line that contains: | |
65 | 59 | |
66 | -6b) Configure varnish to store separate caches for each language | |
67 | - | |
68 | -Add the following line to your /etc/varnish/default.vcl file: | |
60 | +VARNISHNCSA_ENABLED=1 | |
69 | 61 | |
70 | - include "/var/lib/noosfero/etc/noosfero/varnish-accept-language.vcl"; | |
62 | +The varnish log will be written to /var/log/varnish/varnishncsa.log in an | |
63 | +apache-compatible format. You should change your statistics generation software | |
64 | +(e.g. awstats) to use that instead of apache logs. | |
71 | 65 | |
72 | -7) Restart Varnish | |
66 | +5b) Restart Varnish Logging service | |
73 | 67 | |
74 | - # invoke-rc.d varnish restart | |
68 | + # invoke-rc.d varnishncsa restart | |
75 | 69 | |
76 | 70 | Thanks to Cosimo Streppone for varnish-accept-language. See |
77 | 71 | http://github.com/cosimo/varnish-accept-language for more information. |
78 | - | |
79 | - -- Antonio Terceiro <terceiro@colivre.coop.br> Sat, 04 Sep 2010 17:29:27 -0300 | ... | ... |
app/controllers/admin/environment_design_controller.rb
... | ... | @@ -3,7 +3,7 @@ class EnvironmentDesignController < BoxOrganizerController |
3 | 3 | protect 'edit_environment_design', :environment |
4 | 4 | |
5 | 5 | def available_blocks |
6 | - @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock ] | |
6 | + @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] | |
7 | 7 | end |
8 | 8 | |
9 | 9 | end | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -16,7 +16,13 @@ class CmsController < MyProfileController |
16 | 16 | |
17 | 17 | before_filter :login_required, :except => [:suggest_an_article] |
18 | 18 | |
19 | - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish] do |c, user, profile| | |
19 | + protect_if :only => :upload_files do |c, user, profile| | |
20 | + article_id = c.params[:parent_id] | |
21 | + (!article_id.blank? && profile.articles.find(article_id).allow_create?(user)) || | |
22 | + (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) | |
23 | + end | |
24 | + | |
25 | + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files] do |c, user, profile| | |
20 | 26 | user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) |
21 | 27 | end |
22 | 28 | |
... | ... | @@ -92,7 +98,7 @@ class CmsController < MyProfileController |
92 | 98 | @article_types = [] |
93 | 99 | available_article_types.each do |type| |
94 | 100 | @article_types.push({ |
95 | - :name => type.name, | |
101 | + :class => type, | |
96 | 102 | :short_description => type.short_description, |
97 | 103 | :description => type.description |
98 | 104 | }) |
... | ... | @@ -154,7 +160,7 @@ class CmsController < MyProfileController |
154 | 160 | end |
155 | 161 | if request.post? && params[:uploaded_files] |
156 | 162 | params[:uploaded_files].each do |file| |
157 | - @uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent) unless file == '' | |
163 | + @uploaded_files << UploadedFile.create(:uploaded_data => file, :profile => profile, :parent => @parent, :last_changed_by => user) unless file == '' | |
158 | 164 | end |
159 | 165 | @errors = @uploaded_files.select { |f| f.errors.any? } |
160 | 166 | if @errors.any? | ... | ... |
app/controllers/my_profile/tasks_controller.rb
... | ... | @@ -9,7 +9,7 @@ class TasksController < MyProfileController |
9 | 9 | end |
10 | 10 | |
11 | 11 | def processed |
12 | - @tasks = Task.to(profile).finished.sort_by(&:created_at) | |
12 | + @tasks = Task.to(profile).closed.sort_by(&:created_at) | |
13 | 13 | end |
14 | 14 | |
15 | 15 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] | ... | ... |
app/controllers/public/account_controller.rb
... | ... | @@ -4,6 +4,7 @@ class AccountController < ApplicationController |
4 | 4 | |
5 | 5 | before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise] |
6 | 6 | before_filter :redirect_if_logged_in, :only => [:login, :signup] |
7 | + before_filter :protect_from_bots, :only => :signup | |
7 | 8 | |
8 | 9 | # say something nice, you goof! something sweet. |
9 | 10 | def index |
... | ... | @@ -55,6 +56,11 @@ class AccountController < ApplicationController |
55 | 56 | render :action => 'login', :layout => false |
56 | 57 | end |
57 | 58 | |
59 | + def signup_time | |
60 | + key = set_signup_start_time_for_now | |
61 | + render :text => { :ok=>true, :key=>key }.to_json | |
62 | + end | |
63 | + | |
58 | 64 | # action to register an user to the application |
59 | 65 | def signup |
60 | 66 | if @plugins.dispatch(:allow_user_registration).include?(false) |
... | ... | @@ -62,12 +68,9 @@ class AccountController < ApplicationController |
62 | 68 | session[:notice] = _("This environment doesn't allow user registration.") |
63 | 69 | end |
64 | 70 | |
71 | + @block_bot = !!session[:may_be_a_bot] | |
65 | 72 | @invitation_code = params[:invitation_code] |
66 | 73 | begin |
67 | - if params[:user] | |
68 | - params[:user].delete(:password_confirmation_clear) | |
69 | - params[:user].delete(:password_clear) | |
70 | - end | |
71 | 74 | @user = User.new(params[:user]) |
72 | 75 | @user.terms_of_use = environment.terms_of_use |
73 | 76 | @user.environment = environment |
... | ... | @@ -76,19 +79,28 @@ class AccountController < ApplicationController |
76 | 79 | @person = Person.new(params[:profile_data]) |
77 | 80 | @person.environment = @user.environment |
78 | 81 | if request.post? |
79 | - @user.signup! | |
80 | - owner_role = Role.find_by_name('owner') | |
81 | - @user.person.affiliate(@user.person, [owner_role]) if owner_role | |
82 | - invitation = Task.find_by_code(@invitation_code) | |
83 | - if invitation | |
84 | - invitation.update_attributes!({:friend => @user.person}) | |
85 | - invitation.finish | |
86 | - end | |
87 | - if @user.activated? | |
88 | - self.current_user = @user | |
89 | - redirect_to '/' | |
82 | + if may_be_a_bot | |
83 | + set_signup_start_time_for_now | |
84 | + @block_bot = true | |
85 | + session[:may_be_a_bot] = true | |
90 | 86 | else |
91 | - @register_pending = true | |
87 | + if session[:may_be_a_bot] | |
88 | + return false unless verify_recaptcha :model=>@user, :message=>_('Captcha (the human test)') | |
89 | + end | |
90 | + @user.signup! | |
91 | + owner_role = Role.find_by_name('owner') | |
92 | + @user.person.affiliate(@user.person, [owner_role]) if owner_role | |
93 | + invitation = Task.find_by_code(@invitation_code) | |
94 | + if invitation | |
95 | + invitation.update_attributes!({:friend => @user.person}) | |
96 | + invitation.finish | |
97 | + end | |
98 | + if @user.activated? | |
99 | + self.current_user = @user | |
100 | + redirect_to '/' | |
101 | + else | |
102 | + @register_pending = true | |
103 | + end | |
92 | 104 | end |
93 | 105 | end |
94 | 106 | rescue ActiveRecord::RecordInvalid |
... | ... | @@ -97,6 +109,7 @@ class AccountController < ApplicationController |
97 | 109 | @person.errors.delete(:user_id) |
98 | 110 | render :action => 'signup' |
99 | 111 | end |
112 | + clear_signup_start_time | |
100 | 113 | end |
101 | 114 | |
102 | 115 | # action to perform logout from the application |
... | ... | @@ -271,7 +284,36 @@ class AccountController < ApplicationController |
271 | 284 | def no_redirect |
272 | 285 | @cannot_redirect = true |
273 | 286 | end |
274 | - | |
287 | + | |
288 | + def set_signup_start_time_for_now | |
289 | + key = 'signup_start_time_' + rand.to_s.split('.')[1] | |
290 | + Rails.cache.write key, Time.now | |
291 | + key | |
292 | + end | |
293 | + | |
294 | + def get_signup_start_time | |
295 | + Rails.cache.read params[:signup_time_key] | |
296 | + end | |
297 | + | |
298 | + def clear_signup_start_time | |
299 | + Rails.cache.delete params[:signup_time_key] if params[:signup_time_key] | |
300 | + end | |
301 | + | |
302 | + def may_be_a_bot | |
303 | + # No minimum signup delay, no bot test. | |
304 | + return false if environment.min_signup_delay == 0 | |
305 | + | |
306 | + # answering captcha, may be human! | |
307 | + return false if params[:recaptcha_response_field] | |
308 | + | |
309 | + # never set signup_time, hi wget! | |
310 | + signup_start_time = get_signup_start_time | |
311 | + return true if signup_start_time.nil? | |
312 | + | |
313 | + # so fast, so bot. | |
314 | + signup_start_time > ( Time.now - environment.min_signup_delay.seconds ) | |
315 | + end | |
316 | + | |
275 | 317 | def check_answer |
276 | 318 | unless answer_correct |
277 | 319 | @enterprise.block | ... | ... |
app/controllers/public/catalog_controller.rb
1 | 1 | class CatalogController < PublicController |
2 | 2 | needs_profile |
3 | + no_design_blocks | |
3 | 4 | |
4 | 5 | before_filter :check_enterprise_and_environment |
5 | 6 | |
6 | 7 | def index |
7 | - @products = @profile.products.paginate(:order => 'name asc', :per_page => 9, :page => params[:page]) | |
8 | + @category = params[:level] ? ProductCategory.find(params[:level]) : nil | |
9 | + @products = @profile.products.from_category(@category).paginate(:order => 'available desc, highlighted desc, name asc', :per_page => 9, :page => params[:page]) | |
10 | + @categories = ProductCategory.on_level(params[:level]).order(:name) | |
8 | 11 | end |
9 | 12 | |
10 | 13 | protected | ... | ... |
app/controllers/public/content_viewer_controller.rb
... | ... | @@ -25,24 +25,26 @@ class ContentViewerController < ApplicationController |
25 | 25 | return |
26 | 26 | end |
27 | 27 | end |
28 | - | |
29 | - # page not found, give error | |
30 | - if @page.nil? | |
31 | - render_not_found(@path) | |
32 | - return | |
33 | - end | |
34 | 28 | end |
35 | 29 | |
36 | - if !@page.display_to?(user) | |
37 | - if profile.display_info_to?(user) || !profile.visible? | |
38 | - message = _('You are not allowed to view this content. You can contact the owner of this profile to request access then.') | |
30 | + if !@page.nil? && !@page.display_to?(user) | |
31 | + if !profile.public? | |
32 | + private_profile_partial_parameters | |
33 | + render :template => 'profile/_private_profile.rhtml', :status => 403 | |
34 | + else #if !profile.visible? | |
35 | + message = _('You are not allowed to view this content.') | |
36 | + message += ' ' + _('You can contact the owner of this profile to request access then.') | |
39 | 37 | render_access_denied(message) |
40 | - elsif !profile.public? | |
41 | - redirect_to :controller => 'profile', :action => 'index', :profile => profile.identifier | |
42 | 38 | end |
43 | 39 | return |
44 | 40 | end |
45 | 41 | |
42 | + # page not found, give error | |
43 | + if @page.nil? | |
44 | + render_not_found(@path) | |
45 | + return | |
46 | + end | |
47 | + | |
46 | 48 | if request.xhr? && params[:toolbar] |
47 | 49 | render :partial => 'article_toolbar' |
48 | 50 | return | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -368,18 +368,13 @@ class ProfileController < PublicController |
368 | 368 | end |
369 | 369 | |
370 | 370 | def private_profile |
371 | - if profile.person? | |
372 | - @action = :add_friend | |
373 | - @message = _("The content here is available to %s's friends only.") % profile.short_name | |
374 | - else | |
375 | - @action = :join | |
376 | - @message = _('The contents in this community is available to members only.') | |
377 | - end | |
378 | - @no_design_blocks = true | |
371 | + private_profile_partial_parameters | |
379 | 372 | end |
380 | 373 | |
381 | 374 | def invisible_profile |
382 | - render_access_denied(_("This profile is inaccessible. You don't have the permission to view the content here."), _("Oops ... you cannot go ahead here")) | |
375 | + unless profile.is_template? | |
376 | + render_access_denied(_("This profile is inaccessible. You don't have the permission to view the content here."), _("Oops ... you cannot go ahead here")) | |
377 | + end | |
383 | 378 | end |
384 | 379 | |
385 | 380 | def per_page | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -1284,7 +1284,7 @@ module ApplicationHelper |
1284 | 1284 | (user.already_reported?(profile) ? |
1285 | 1285 | content_tag('a', text, :class => klass + ' disabled comment-footer comment-footer-link', :title => already_reported_message) : |
1286 | 1286 | link_to(text, url, :class => klass + ' comment-footer comment-footer-link', :title => report_profile_message) |
1287 | - ) + content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide') | |
1287 | + ) + content_tag('span', ' ', :class => 'comment-footer comment-footer-hide') | |
1288 | 1288 | end |
1289 | 1289 | end |
1290 | 1290 | |
... | ... | @@ -1337,11 +1337,12 @@ module ApplicationHelper |
1337 | 1337 | counter = 0 |
1338 | 1338 | radios = klass.templates.map do |template| |
1339 | 1339 | counter += 1 |
1340 | - content_tag('li', labelled_radio_button(template.name, "#{field_name}[template_id]", template.id, counter==1)) | |
1340 | + content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, counter==1)) | |
1341 | 1341 | end.join("\n") |
1342 | 1342 | |
1343 | - content_tag('div', content_tag('span', _('Template:')) + | |
1344 | - content_tag('ul', radios, :style => 'list-style: none; padding-left: 0; margin-top: 0.5em;'), | |
1343 | + content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') + | |
1344 | + content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') + | |
1345 | + content_tag('ul', radios, :style => 'list-style: none; padding-left: 20px; margin-top: 0.5em;'), | |
1345 | 1346 | :id => 'template-options', |
1346 | 1347 | :style => 'margin-top: 1em' |
1347 | 1348 | ) |
... | ... | @@ -1410,4 +1411,16 @@ module ApplicationHelper |
1410 | 1411 | options[:class] = "comment-footer comment-footer-link comment-footer-hide" |
1411 | 1412 | expirable_content_reference content, action, text, url, options |
1412 | 1413 | end |
1414 | + | |
1415 | + def private_profile_partial_parameters | |
1416 | + if profile.person? | |
1417 | + @action = :add_friend | |
1418 | + @message = _("The content here is available to %s's friends only.") % profile.short_name | |
1419 | + else | |
1420 | + @action = :join | |
1421 | + @message = _('The contents in this community is available to members only.') | |
1422 | + end | |
1423 | + @no_design_blocks = true | |
1424 | + end | |
1425 | + | |
1413 | 1426 | end | ... | ... |
app/helpers/catalog_helper.rb
... | ... | @@ -3,4 +3,28 @@ module CatalogHelper |
3 | 3 | include DisplayHelper |
4 | 4 | include ManageProductsHelper |
5 | 5 | |
6 | + def breadcrumb(category) | |
7 | + start = link_to(_('Start'), {:action => 'index'}) | |
8 | + ancestors = category.ancestors.map { |c| link_to(c.name, {:action => 'index', :level => c.id}) }.reverse | |
9 | + current_level = content_tag('strong', category.name) | |
10 | + all_items = [start] + ancestors + [current_level] | |
11 | + content_tag('div', all_items.join(' → '), :id => 'breadcrumb') | |
12 | + end | |
13 | + | |
14 | + def category_link(category, sub = false) | |
15 | + count = profile.products.from_category(category).count | |
16 | + name = truncate(category.name, :length => 22 - count.to_s.size) | |
17 | + link_name = sub ? name : content_tag('strong', name) | |
18 | + link = link_to(link_name, {:action => 'index', :level => category.id}, :title => category.name) | |
19 | + content_tag('li', "#{link} (#{count})") if count > 0 | |
20 | + end | |
21 | + | |
22 | + def category_sub_links(category) | |
23 | + sub_categories = [] | |
24 | + category.children.order(:name).each do |sub_category| | |
25 | + sub_categories << category_link(sub_category, true) | |
26 | + end | |
27 | + content_tag('ul', sub_categories) if sub_categories.size > 1 | |
28 | + end | |
29 | + | |
6 | 30 | end | ... | ... |
app/helpers/content_viewer_helper.rb
... | ... | @@ -26,7 +26,7 @@ module ContentViewerHelper |
26 | 26 | end |
27 | 27 | title << content_tag('span', |
28 | 28 | content_tag('span', show_date(article.published_at), :class => 'date') + |
29 | - content_tag('span', [_(", by %s") % link_to(article.author_name, article.author.url)], :class => 'author') + | |
29 | + content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') + | |
30 | 30 | content_tag('span', comments, :class => 'comments'), |
31 | 31 | :class => 'created-at' |
32 | 32 | ) | ... | ... |
app/helpers/display_helper.rb
... | ... | @@ -8,6 +8,14 @@ module DisplayHelper |
8 | 8 | opts |
9 | 9 | end |
10 | 10 | |
11 | + def themed_path(file) | |
12 | + if File.exists?(File.join(Rails.root, 'public', theme_path, file)) | |
13 | + File.join(theme_path, file) | |
14 | + else | |
15 | + file | |
16 | + end | |
17 | + end | |
18 | + | |
11 | 19 | def image_link_to_product(product, opts={}) |
12 | 20 | return _('No product') unless product |
13 | 21 | target = product_path(product) | ... | ... |
app/helpers/folder_helper.rb
... | ... | @@ -52,8 +52,8 @@ module FolderHelper |
52 | 52 | end |
53 | 53 | end |
54 | 54 | |
55 | - def icon_for_new_article(type) | |
56 | - "icon-new icon-new%s" % type.constantize.icon_name | |
55 | + def icon_for_new_article(klass) | |
56 | + "icon-new icon-new%s" % klass.icon_name | |
57 | 57 | end |
58 | 58 | |
59 | 59 | def custom_options_for_article(article) | ... | ... |
app/helpers/forms_helper.rb
... | ... | @@ -142,6 +142,38 @@ module FormsHelper |
142 | 142 | content_tag('table',rows.join("\n")) |
143 | 143 | end |
144 | 144 | |
145 | + def select_folder(label_text, field_id, collection, default_value=nil, html_options = {}, js_options = {}) | |
146 | + root = profile ? profile.identifier : _("root") | |
147 | + labelled_form_field( | |
148 | + label_text, | |
149 | + select_tag( | |
150 | + field_id, | |
151 | + options_for_select( | |
152 | + [[root, '']] + | |
153 | + collection.collect {|f| [ root + '/' + f.full_name, f.id ] }, | |
154 | + default_value | |
155 | + ), | |
156 | + html_options.merge(js_options) | |
157 | + ) | |
158 | + ) | |
159 | + end | |
160 | + | |
161 | + def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}) | |
162 | + result = labelled_form_field( | |
163 | + label_text, | |
164 | + select_tag( | |
165 | + field_id, | |
166 | + options_for_select( | |
167 | + [[profile.identifier, '']] + | |
168 | + profile.folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] }, | |
169 | + default_value | |
170 | + ), | |
171 | + html_options.merge(js_options) | |
172 | + ) | |
173 | + ) | |
174 | + return result | |
175 | + end | |
176 | + | |
145 | 177 | def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) |
146 | 178 | datepicker_options[:disabled] ||= false |
147 | 179 | datepicker_options[:alt_field] ||= '' | ... | ... |
app/helpers/language_helper.rb
... | ... | @@ -13,19 +13,20 @@ module LanguageHelper |
13 | 13 | |
14 | 14 | alias :calendar_date_select_language :tinymce_language |
15 | 15 | |
16 | - def language_chooser(environment, options = {}) | |
17 | - return if environment.locales.size < 2 | |
16 | + def language_chooser(environment=nil, options = {}) | |
17 | + locales = environment.nil? ? Noosfero.locales : environment.locales | |
18 | + return if locales.size < 2 | |
18 | 19 | current = language |
19 | 20 | separator = options[:separator] || ' — ' |
20 | 21 | |
21 | 22 | if options[:element] == 'dropdown' |
22 | 23 | select_tag('lang', |
23 | - options_for_select(environment.locales.map{|code,name| [name, code]}, current), | |
24 | + options_for_select(locales.map{|code,name| [name, code]}, current), | |
24 | 25 | :onchange => "document.location.href= #{url_for(params.merge(:lang => 'LANGUAGE')).inspect}.replace(/LANGUAGE/, this.value) ;", |
25 | 26 | :help => _('The language you choose here is the language used for options, buttons, etc. It does not affect the language of the content created by other users.') |
26 | 27 | ) |
27 | 28 | else |
28 | - languages = environment.locales.map do |code,name| | |
29 | + languages = locales.map do |code,name| | |
29 | 30 | if code == current |
30 | 31 | content_tag('strong', name) |
31 | 32 | else | ... | ... |
app/models/approve_article.rb
... | ... | @@ -48,7 +48,7 @@ class ApproveArticle < Task |
48 | 48 | end |
49 | 49 | |
50 | 50 | def perform |
51 | - article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source) | |
51 | + article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.author_id) | |
52 | 52 | end |
53 | 53 | |
54 | 54 | def title | ... | ... |
app/models/article.rb
... | ... | @@ -13,10 +13,18 @@ class Article < ActiveRecord::Base |
13 | 13 | # xss_terminate plugin can't sanitize array fields |
14 | 14 | before_save :sanitize_tag_list |
15 | 15 | |
16 | + before_create do |article| | |
17 | + if article.last_changed_by_id | |
18 | + article.author_name = Person.find(article.last_changed_by_id).name | |
19 | + end | |
20 | + end | |
21 | + | |
16 | 22 | belongs_to :profile |
17 | 23 | validates_presence_of :profile_id, :name |
18 | 24 | validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? } |
19 | 25 | |
26 | + validates_length_of :name, :maximum => 150 | |
27 | + | |
20 | 28 | validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? } |
21 | 29 | |
22 | 30 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' |
... | ... | @@ -289,7 +297,7 @@ class Article < ActiveRecord::Base |
289 | 297 | if last_comment |
290 | 298 | {:date => last_comment.created_at, :author_name => last_comment.author_name, :author_url => last_comment.author_url} |
291 | 299 | else |
292 | - {:date => updated_at, :author_name => author.name, :author_url => author.url} | |
300 | + {:date => updated_at, :author_name => author_name, :author_url => author_url} | |
293 | 301 | end |
294 | 302 | end |
295 | 303 | |
... | ... | @@ -441,7 +449,7 @@ class Article < ActiveRecord::Base |
441 | 449 | end |
442 | 450 | |
443 | 451 | def allow_post_content?(user = nil) |
444 | - user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == self.creator)) | |
452 | + user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author)) | |
445 | 453 | end |
446 | 454 | |
447 | 455 | def allow_publish_content?(user = nil) |
... | ... | @@ -496,7 +504,6 @@ class Article < ActiveRecord::Base |
496 | 504 | :slug, |
497 | 505 | :updated_at, |
498 | 506 | :created_at, |
499 | - :last_changed_by_id, | |
500 | 507 | :version, |
501 | 508 | :lock_version, |
502 | 509 | :type, |
... | ... | @@ -539,15 +546,24 @@ class Article < ActiveRecord::Base |
539 | 546 | end |
540 | 547 | |
541 | 548 | def author |
542 | - if reference_article | |
543 | - reference_article.author | |
549 | + if versions.empty? | |
550 | + last_changed_by | |
544 | 551 | else |
545 | - last_changed_by || profile | |
552 | + author_id = versions.first.last_changed_by_id | |
553 | + Person.exists?(author_id) ? Person.find(author_id) : nil | |
546 | 554 | end |
547 | 555 | end |
548 | 556 | |
549 | 557 | def author_name |
550 | - setting[:author_name].blank? ? author.name : setting[:author_name] | |
558 | + author ? author.name : (setting[:author_name] || _('Unknown')) | |
559 | + end | |
560 | + | |
561 | + def author_url | |
562 | + author ? author.url : nil | |
563 | + end | |
564 | + | |
565 | + def author_id | |
566 | + author ? author.id : nil | |
551 | 567 | end |
552 | 568 | |
553 | 569 | alias :active_record_cache_key :cache_key |
... | ... | @@ -572,11 +588,6 @@ class Article < ActiveRecord::Base |
572 | 588 | truncate sanitize_html(self.lead), :length => 170, :omission => '...' |
573 | 589 | end |
574 | 590 | |
575 | - def creator | |
576 | - creator_id = versions[0][:last_changed_by_id] | |
577 | - creator_id && Profile.find(creator_id) | |
578 | - end | |
579 | - | |
580 | 591 | def notifiable? |
581 | 592 | false |
582 | 593 | end | ... | ... |
app/models/category.rb
... | ... | @@ -13,6 +13,16 @@ class Category < ActiveRecord::Base |
13 | 13 | {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} |
14 | 14 | } |
15 | 15 | |
16 | + named_scope :on_level, lambda { |parent| {:conditions => {:parent_id => parent}} } | |
17 | + | |
18 | + named_scope :sub_categories, lambda { |category| | |
19 | + {:conditions => ['categories.path LIKE ? AND categories.id != ?', "%#{category.slug}%", category.id]} | |
20 | + } | |
21 | + | |
22 | + named_scope :sub_tree, lambda { |category| | |
23 | + {:conditions => ['categories.path LIKE ?', "%#{category.slug}%"]} | |
24 | + } | |
25 | + | |
16 | 26 | acts_as_filesystem |
17 | 27 | |
18 | 28 | has_many :article_categorizations, :dependent => :destroy | ... | ... |
app/models/comment.rb
... | ... | @@ -74,6 +74,10 @@ class Comment < ActiveRecord::Base |
74 | 74 | self.find(:all, :order => 'created_at desc, id desc', :limit => limit) |
75 | 75 | end |
76 | 76 | |
77 | + def notification_emails | |
78 | + self.article.profile.notification_emails - [self.author_email || self.email] | |
79 | + end | |
80 | + | |
77 | 81 | after_save :notify_article |
78 | 82 | after_destroy :notify_article |
79 | 83 | def notify_article |
... | ... | @@ -114,7 +118,7 @@ class Comment < ActiveRecord::Base |
114 | 118 | |
115 | 119 | def notify_by_mail |
116 | 120 | if source.kind_of?(Article) && article.notify_comments? |
117 | - if !article.profile.notification_emails.empty? | |
121 | + if !notification_emails.empty? | |
118 | 122 | Comment::Notifier.deliver_mail(self) |
119 | 123 | end |
120 | 124 | emails = article.followers - [author_email] |
... | ... | @@ -174,7 +178,7 @@ class Comment < ActiveRecord::Base |
174 | 178 | class Notifier < ActionMailer::Base |
175 | 179 | def mail(comment) |
176 | 180 | profile = comment.article.profile |
177 | - recipients profile.notification_emails | |
181 | + recipients comment.notification_emails | |
178 | 182 | from "#{profile.environment.name} <#{profile.environment.contact_email}>" |
179 | 183 | subject _("[%s] you got a new comment!") % [profile.environment.name] |
180 | 184 | body :recipient => profile.nickname || profile.name, |
... | ... | @@ -224,6 +228,7 @@ class Comment < ActiveRecord::Base |
224 | 228 | def spam! |
225 | 229 | self.spam = true |
226 | 230 | self.save! |
231 | + SpammerLogger.log(ip_address, self) | |
227 | 232 | Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) |
228 | 233 | self |
229 | 234 | end | ... | ... |
app/models/enterprise_homepage.rb
app/models/environment.rb
... | ... | @@ -233,8 +233,10 @@ class Environment < ActiveRecord::Base |
233 | 233 | settings[:message_for_member_invitation] || InviteMember.mail_template |
234 | 234 | end |
235 | 235 | |
236 | + settings_items :min_signup_delay, :type => Integer, :default => 3 #seconds | |
236 | 237 | settings_items :activation_blocked_text, :type => String |
237 | - settings_items :message_for_disabled_enterprise, :type => String | |
238 | + settings_items :message_for_disabled_enterprise, :type => String, | |
239 | + :default => _('This enterprise needs to be enabled.') | |
238 | 240 | settings_items :location, :type => String |
239 | 241 | settings_items :layout_template, :type => String, :default => 'default' |
240 | 242 | settings_items :homepage, :type => String |
... | ... | @@ -616,12 +618,10 @@ class Environment < ActiveRecord::Base |
616 | 618 | end |
617 | 619 | |
618 | 620 | def top_url |
619 | - protocol = 'http' | |
620 | - result = "#{protocol}://#{default_hostname}" | |
621 | - if Noosfero.url_options.has_key?(:port) | |
622 | - result << ':' << Noosfero.url_options[:port].to_s | |
623 | - end | |
624 | - result | |
621 | + url = 'http://' | |
622 | + url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) | |
623 | + url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) | |
624 | + url | |
625 | 625 | end |
626 | 626 | |
627 | 627 | def to_s | ... | ... |
app/models/event.rb
... | ... | @@ -38,7 +38,7 @@ class Event < Article |
38 | 38 | filter_iframes :body, :link, :address, :whitelist => lambda { profile && profile.environment && profile.environment.trusted_sites_for_iframe } |
39 | 39 | |
40 | 40 | def self.description |
41 | - _('A calendar event') | |
41 | + _('A calendar event.') | |
42 | 42 | end |
43 | 43 | |
44 | 44 | def self.short_description | ... | ... |
app/models/organization.rb
... | ... | @@ -78,6 +78,8 @@ class Organization < Profile |
78 | 78 | country |
79 | 79 | tag_list |
80 | 80 | template_id |
81 | + district | |
82 | + address_reference | |
81 | 83 | ] |
82 | 84 | |
83 | 85 | def self.fields |
... | ... | @@ -96,8 +98,8 @@ class Organization < Profile |
96 | 98 | [] |
97 | 99 | end |
98 | 100 | |
99 | - N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list') | |
100 | - settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information | |
101 | + N_('Display name'); N_('Description'); N_('Contact person'); N_('Contact email'); N_('Acronym'); N_('Foundation year'); N_('Legal form'); N_('Economic activity'); N_('Management information'); N_('Tag list'); N_('District'); N_('Address reference') | |
102 | + settings_items :display_name, :description, :contact_person, :contact_email, :acronym, :foundation_year, :legal_form, :economic_activity, :management_information, :district, :address_reference | |
101 | 103 | |
102 | 104 | validates_format_of :foundation_year, :with => Noosfero::Constants::INTEGER_FORMAT |
103 | 105 | validates_format_of :contact_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |org| !org.contact_email.blank? }) | ... | ... |
app/models/person.rb
... | ... | @@ -67,6 +67,9 @@ class Person < Profile |
67 | 67 | :order => 'total DESC', |
68 | 68 | :conditions => ['action_tracker.created_at >= ? OR action_tracker.id IS NULL', ActionTracker::Record::RECENT_DELAY.days.ago] |
69 | 69 | |
70 | + named_scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*' | |
71 | + named_scope :non_abusers, :joins => "LEFT JOIN tasks ON profiles.id = tasks.requestor_id AND tasks.type='AbuseComplaint'", :conditions => ["tasks.status != 3 OR tasks.id is NULL"], :select => "DISTINCT profiles.*" | |
72 | + | |
70 | 73 | after_destroy do |person| |
71 | 74 | Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } |
72 | 75 | end |
... | ... | @@ -144,6 +147,9 @@ class Person < Profile |
144 | 147 | contact_phone |
145 | 148 | contact_information |
146 | 149 | description |
150 | + image | |
151 | + district | |
152 | + address_reference | |
147 | 153 | ] |
148 | 154 | |
149 | 155 | validates_multiparameter_assignments |
... | ... | @@ -198,8 +204,8 @@ class Person < Profile |
198 | 204 | N_('Education'); N_('Custom education'); N_('Custom area of study'); |
199 | 205 | settings_items :formation, :custom_formation, :custom_area_of_study |
200 | 206 | |
201 | - N_('Contact information'); N_('City'); N_('State'); N_('Country'); N_('Sex'); N_('Zip code') | |
202 | - settings_items :photo, :contact_information, :sex, :city, :state, :country, :zip_code | |
207 | + N_('Contact information'); N_('City'); N_('State'); N_('Country'); N_('Sex'); N_('Zip code'); N_('District'); N_('Address reference') | |
208 | + settings_items :photo, :contact_information, :sex, :city, :state, :country, :zip_code, :district, :address_reference | |
203 | 209 | |
204 | 210 | extend SetProfileRegionFromCityState::ClassMethods |
205 | 211 | set_profile_region_from_city_state |
... | ... | @@ -440,6 +446,10 @@ class Person < Profile |
440 | 446 | abuse_report.save! |
441 | 447 | end |
442 | 448 | |
449 | + def abuser? | |
450 | + AbuseComplaint.finished.where(:requestor_id => self).count > 0 | |
451 | + end | |
452 | + | |
443 | 453 | def control_panel_settings_button |
444 | 454 | {:title => _('Edit Profile'), :icon => 'edit-profile'} |
445 | 455 | end | ... | ... |
app/models/product.rb
... | ... | @@ -23,6 +23,10 @@ class Product < ActiveRecord::Base |
23 | 23 | |
24 | 24 | named_scope :more_recent, :order => "created_at DESC" |
25 | 25 | |
26 | + named_scope :from_category, lambda { |category| | |
27 | + {:joins => :product_category, :conditions => ['categories.path LIKE ?', "%#{category.slug}%"]} if category | |
28 | + } | |
29 | + | |
26 | 30 | after_update :save_image |
27 | 31 | |
28 | 32 | def lat | ... | ... |
app/models/profile.rb
... | ... | @@ -141,6 +141,10 @@ class Profile < ActiveRecord::Base |
141 | 141 | |
142 | 142 | acts_as_having_settings :field => :data |
143 | 143 | |
144 | + def settings | |
145 | + data | |
146 | + end | |
147 | + | |
144 | 148 | settings_items :redirect_l10n, :type => :boolean, :default => false |
145 | 149 | settings_items :public_content, :type => :boolean, :default => true |
146 | 150 | settings_items :description |
... | ... | @@ -229,7 +233,7 @@ class Profile < ActiveRecord::Base |
229 | 233 | if myregion |
230 | 234 | myregion.hierarchy.reverse.first(2).map(&:name).join(separator) |
231 | 235 | else |
232 | - %w[address city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator) | |
236 | + %w[address district city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator) | |
233 | 237 | end |
234 | 238 | end |
235 | 239 | |
... | ... | @@ -463,6 +467,10 @@ class Profile < ActiveRecord::Base |
463 | 467 | { :profile => identifier, :controller => 'profile_editor', :action => 'index' } |
464 | 468 | end |
465 | 469 | |
470 | + def tasks_url | |
471 | + { :profile => identifier, :controller => 'tasks', :action => 'index', :host => default_hostname } | |
472 | + end | |
473 | + | |
466 | 474 | def leave_url(reload = false) |
467 | 475 | { :profile => identifier, :controller => 'profile', :action => 'leave', :reload => reload } |
468 | 476 | end |
... | ... | @@ -694,7 +702,7 @@ private :generate_url, :url_options |
694 | 702 | def custom_footer_expanded |
695 | 703 | footer = custom_footer |
696 | 704 | if footer |
697 | - %w[contact_person contact_email contact_phone location address economic_activity city state country zip_code].each do |att| | |
705 | + %w[contact_person contact_email contact_phone location address district address_reference economic_activity city state country zip_code].each do |att| | |
698 | 706 | if self.respond_to?(att) && footer.match(/\{[^{]*#{att}\}/) |
699 | 707 | if !self.send(att).nil? && !self.send(att).blank? |
700 | 708 | footer = footer.gsub(/\{([^{]*)#{att}\}/, '\1' + self.send(att)) | ... | ... |
app/models/raw_html_article.rb
... | ... | @@ -5,11 +5,11 @@ class RawHTMLArticle < TextArticle |
5 | 5 | end |
6 | 6 | |
7 | 7 | def self.short_description |
8 | - _('Raw HTML text article.') | |
8 | + _('Raw HTML text article') | |
9 | 9 | end |
10 | 10 | |
11 | 11 | def self.description |
12 | - _('Allows HTML without filter (only for admins)') | |
12 | + _('Allows HTML without filter (only for admins).') | |
13 | 13 | end |
14 | 14 | |
15 | 15 | xss_terminate :only => [ ] | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +class SpammerLogger < Logger | |
2 | + @logpath = File.join(Rails.root, 'log', "#{ENV['RAILS_ENV']}_spammers.log") | |
3 | + @logger = new(@logpath) | |
4 | + | |
5 | + def self.log(spammer_ip, object=nil) | |
6 | + if object | |
7 | + if object.kind_of?(Comment) | |
8 | + @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n" | |
9 | + end | |
10 | + else | |
11 | + @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n" | |
12 | + end | |
13 | + end | |
14 | + | |
15 | + def self.clean_log | |
16 | + File.delete(@logpath) if File.exists?(@logpath) | |
17 | + end | |
18 | + | |
19 | + def self.reload_log | |
20 | + clean_log | |
21 | + @logger = new(@logpath) | |
22 | + end | |
23 | + | |
24 | +end | ... | ... |
app/models/tags_block.rb
... | ... | @@ -20,7 +20,8 @@ class TagsBlock < Block |
20 | 20 | end |
21 | 21 | |
22 | 22 | def content(args={}) |
23 | - tags = owner.article_tags | |
23 | + is_env = owner.class == Environment | |
24 | + tags = is_env ? owner.tag_counts : owner.article_tags | |
24 | 25 | return '' if tags.empty? |
25 | 26 | |
26 | 27 | if limit |
... | ... | @@ -29,18 +30,28 @@ class TagsBlock < Block |
29 | 30 | tags_tmp.map{ |k,v| tags[k] = v } |
30 | 31 | end |
31 | 32 | |
33 | + url = is_env ? {:host=>owner.default_hostname, :controller=>'search', :action => 'tag'} : | |
34 | + owner.public_profile_url.merge(:controller => 'profile', :action => 'tags') | |
35 | + tagname_option = is_env ? :tag : :id | |
36 | + | |
32 | 37 | block_title(title) + |
33 | 38 | "\n<div class='tag_cloud'>\n"+ |
34 | - tag_cloud( tags, :id, | |
35 | - owner.public_profile_url.merge(:controller => 'profile', :action => 'tags'), | |
36 | - :max_size => 16, :min_size => 9 ) + | |
39 | + tag_cloud( tags, tagname_option, url, :max_size => 16, :min_size => 9 ) + | |
37 | 40 | "\n</div><!-- end class='tag_cloud' -->\n"; |
38 | 41 | end |
39 | 42 | |
40 | 43 | def footer |
41 | - owner_id = owner.identifier | |
42 | - lambda do | |
43 | - link_to s_('tags|View all'), :profile => owner_id, :controller => 'profile', :action => 'tags' | |
44 | + if owner.class == Environment | |
45 | + lambda do | |
46 | + link_to s_('tags|View all'), | |
47 | + :controller => 'search', :action => 'tags' | |
48 | + end | |
49 | + else | |
50 | + owner_id = owner.identifier | |
51 | + lambda do | |
52 | + link_to s_('tags|View all'), | |
53 | + :profile => owner_id, :controller => 'profile', :action => 'tags' | |
54 | + end | |
44 | 55 | end |
45 | 56 | end |
46 | 57 | ... | ... |
app/models/task.rb
... | ... | @@ -267,7 +267,10 @@ class Task < ActiveRecord::Base |
267 | 267 | end |
268 | 268 | |
269 | 269 | named_scope :pending, :conditions => { :status => Task::Status::ACTIVE } |
270 | - named_scope :finished, :conditions => { :status => [Task::Status::CANCELLED, Task::Status::FINISHED] } | |
270 | + named_scope :hidden, :conditions => { :status => Task::Status::HIDDEN } | |
271 | + named_scope :finished, :conditions => { :status => Task::Status::FINISHED } | |
272 | + named_scope :canceled, :conditions => { :status => Task::Status::CANCELLED } | |
273 | + named_scope :closed, :conditions => { :status => [Task::Status::CANCELLED, Task::Status::FINISHED] } | |
271 | 274 | named_scope :opened, :conditions => { :status => [Task::Status::ACTIVE, Task::Status::HIDDEN] } |
272 | 275 | named_scope :of, lambda { |type| conditions = type ? "type LIKE '#{type}'" : "1=1"; {:conditions => [conditions]} } |
273 | 276 | named_scope :order_by, lambda { |attribute, ord| {:order => "#{attribute} #{ord}"} } | ... | ... |
app/models/task_mailer.rb
... | ... | @@ -14,7 +14,7 @@ class TaskMailer < ActionMailer::Base |
14 | 14 | |
15 | 15 | recipients task.target.notification_emails |
16 | 16 | |
17 | - url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.url.merge(:controller => 'tasks', :action => 'index')) | |
17 | + url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url) | |
18 | 18 | |
19 | 19 | from self.class.generate_from(task) |
20 | 20 | subject '[%s] %s' % [task.environment.name, task.target_notification_description] | ... | ... |
app/models/tiny_mce_article.rb
app/models/user.rb
... | ... | @@ -15,7 +15,7 @@ class User < ActiveRecord::Base |
15 | 15 | # FIXME ugly workaround |
16 | 16 | def self.human_attribute_name(attrib) |
17 | 17 | case attrib.to_sym |
18 | - when :login: return _('Username') | |
18 | + when :login: return [_('Username'), _('Email')].join(' / ') | |
19 | 19 | when :email: return _('e-Mail') |
20 | 20 | else _(self.superclass.human_attribute_name(attrib)) |
21 | 21 | end |
... | ... | @@ -31,7 +31,7 @@ class User < ActiveRecord::Base |
31 | 31 | after_create do |user| |
32 | 32 | user.person ||= Person.new |
33 | 33 | user.person.attributes = user.person_data.merge(:identifier => user.login, :user => user, :environment_id => user.environment_id) |
34 | - user.person.name ||= user.login | |
34 | + user.person.name ||= user.name | |
35 | 35 | user.person.visible = false unless user.activated? |
36 | 36 | user.person.save! |
37 | 37 | if user.environment.enabled?('skip_new_user_email_confirmation') |
... | ... | @@ -116,10 +116,11 @@ class User < ActiveRecord::Base |
116 | 116 | |
117 | 117 | validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('%{fn} must be checked in order to signup.').fix_i18n |
118 | 118 | |
119 | - # Authenticates a user by their login name and unencrypted password. Returns the user or nil. | |
119 | + # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil. | |
120 | 120 | def self.authenticate(login, password, environment = nil) |
121 | 121 | environment ||= Environment.default |
122 | - u = first :conditions => ['login = ? AND environment_id = ? AND activated_at IS NOT NULL', login, environment.id] # need to get the salt | |
122 | + u = self.first :conditions => ['(login = ? OR email = ?) AND environment_id = ? AND activated_at IS NOT NULL', | |
123 | + login, login, environment.id] # need to get the salt | |
123 | 124 | u && u.authenticated?(password) ? u : nil |
124 | 125 | end |
125 | 126 | ... | ... |
app/views/account/_signup_form.rhtml
1 | -<%= error_messages_for :user, :person %> | |
1 | +<% if @block_bot %> | |
2 | + <div class="atention" style="font-size: 150%;"> | |
3 | + <strong><%=_('Are you a robot?')%></strong> <br /> | |
4 | + <%=_('Please, prove that you are human by filling the captcha.')%> | |
5 | + </div> | |
6 | +<% end %> | |
7 | + | |
8 | +<% @profile_data = @person %> | |
9 | + | |
10 | +<%= error_messages_for :user, :person, :header_message => _('The account could not be created') %> | |
11 | + | |
12 | +<% labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form', :honeypot => true } do |f| %> | |
2 | 13 | |
3 | -<% labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form' } do |f| %> | |
14 | +<input type="hidden" id="signup_time_key" name="signup_time_key" /> | |
15 | +<script type="text/javascript"> | |
16 | + jQuery.ajax({ | |
17 | + type: "POST", | |
18 | + url: "<%= url_for :controller=>'account', :action=>'signup_time' %>", | |
19 | + dataType: 'json', | |
20 | + success: function(data) { | |
21 | + if (data.ok) jQuery('#signup_time_key').val(data.key); | |
22 | + } | |
23 | + }); | |
24 | +</script> | |
4 | 25 | |
5 | 26 | <%= hidden_field_tag :invitation_code, @invitation_code %> |
6 | 27 | |
7 | 28 | <div id='signup-form-header'> |
8 | 29 | |
9 | - <span id="signup-domain"><%= environment.default_hostname %>/</span> | |
10 | - <div id='signup-login'> | |
11 | - <div id='signup-login-field'> | |
12 | - <%= required f.text_field(:login, :onchange => 'this.value = convToValidLogin(this.value);', :rel => s_('signup|Login')) %> | |
13 | - <div id='url-check'><p> </p></div> | |
30 | + <div id='signup-formfield-group'> | |
31 | + <%= label(:user, :login, _('Username'), {:class => 'formlabel'}) %> | |
32 | + <span id="signup-domain"><%= environment.default_hostname %>/</span> | |
33 | + <div id='signup-login'> | |
34 | + <div id='signup-login-field' class='formfield'> | |
35 | + <%= required text_field(:user, :login, :id => 'user_login', | |
36 | + :onchange => 'this.value = convToValidUsername(this.value);') %> | |
37 | + <div id='url-check'><p> </p></div> | |
38 | + </div> | |
39 | + <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %> | |
40 | + <br style="clear: both;" /> | |
14 | 41 | </div> |
15 | - <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %> | |
16 | - <br style="clear: both;" /> | |
17 | 42 | </div> |
18 | 43 | <%= observe_field 'user_login', |
19 | 44 | :url => { :action => 'check_url' }, |
... | ... | @@ -26,20 +51,19 @@ |
26 | 51 | |
27 | 52 | <div id='signup-password'> |
28 | 53 | <%= required f.password_field(:password, :id => 'user_pw') %> |
29 | - <%= f.text_field(:password_clear, :value => _('password')) %> | |
30 | 54 | <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %> |
31 | 55 | <div id='fake-check'><p> </p></div> |
32 | 56 | </div> |
33 | 57 | |
34 | 58 | <div id='signup-password-confirmation'> |
35 | 59 | <%= required f.password_field(:password_confirmation) %> |
36 | - <%= f.text_field(:password_confirmation_clear, :value => _('password confirmation')) %> | |
60 | + <%= content_tag(:small,_('We need to be sure that you filled in your password correctly. Confirm you password.'), :id => 'password-confirmation-balloon') %> | |
37 | 61 | <div id='password-check'><p> </p></div> |
38 | 62 | </div> |
39 | 63 | |
40 | 64 | <div id='signup-email'> |
41 | - <%= required f.text_field(:email, :rel => _('e-Mail')) %> | |
42 | - <%= content_tag(:small,_('This e-mail address will be used to contact you.')) %> | |
65 | + <%= required f.text_field(:email) %> | |
66 | + <%= content_tag(:small,_('This e-mail address will be used to contact you.'), :id => 'email-balloon') %> | |
43 | 67 | <div id='email-check'><p> </p></div> |
44 | 68 | </div> |
45 | 69 | <%= observe_field "user_email", |
... | ... | @@ -62,21 +86,23 @@ |
62 | 86 | }" |
63 | 87 | %> |
64 | 88 | |
65 | - <%= label :profile_data, :name %> | |
66 | - <%= required text_field(:profile_data, :name, :rel => _('Full name')) %> | |
89 | + <div id='signup-name'> | |
90 | + <%= labelled_form_field(_('Full name'), text_field(:profile_data, :name)) %> | |
91 | + <%= content_tag(:small,_('Tell us your name, it will be used to identify yourself.'), :id => 'name-balloon') %> | |
92 | + </div> | |
67 | 93 | |
68 | 94 | </div> |
69 | 95 | |
70 | 96 | <div id="signup-form-profile"> |
71 | 97 | |
72 | - <%= template_options(Person, 'profile_data') %> | |
73 | - | |
74 | 98 | <% labelled_fields_for :profile_data, @person do |f| %> |
75 | 99 | <%= render :partial => 'profile_editor/person_form', :locals => {:f => f} %> |
76 | 100 | <% end %> |
77 | 101 | |
78 | 102 | <%= @plugins.dispatch(:signup_extra_contents).collect { |content| instance_eval(&content) }.join("") %> |
79 | 103 | |
104 | + <%= template_options(Person, 'profile_data') %> | |
105 | + | |
80 | 106 | <% unless @terms_of_use.blank? %> |
81 | 107 | <div id='terms-of-use-box' class='formfieldline'> |
82 | 108 | <%= labelled_check_box(_('I accept the %s') % link_to(_('terms of use'), {:controller => 'home', :action => 'terms'}, :target => '_blank'), 'user[terms_accepted]') %> |
... | ... | @@ -91,6 +117,8 @@ |
91 | 117 | <% end %> |
92 | 118 | </div> |
93 | 119 | |
120 | +<%= recaptcha_tags :ajax => true, :display => {:theme => 'clean'} if @block_bot %> | |
121 | + | |
94 | 122 | <p style="text-align: center"> |
95 | 123 | <%= submit_button('save', _('Create my account')) %> |
96 | 124 | </p> |
... | ... | @@ -99,70 +127,59 @@ |
99 | 127 | |
100 | 128 | <script type="text/javascript"> |
101 | 129 | jQuery(function($) { |
130 | + | |
131 | + $('#signup-form #user_login').css('width', 335 - $('#signup-domain').outerWidth()); | |
132 | + | |
102 | 133 | $('#signup-form input[type=text], #signup-form textarea').each(function() { |
103 | - if ($(this).attr('rel')) var default_value = $(this).attr('rel').toLowerCase(); | |
104 | - if ($(this).val() == '') $(this).val(default_value); | |
105 | - $(this).bind('focus', function() { | |
106 | - if ($(this).val() == default_value) $(this).val(''); | |
107 | - }); | |
108 | 134 | $(this).bind('blur', function() { |
109 | 135 | if ($(this).val() == '') { |
110 | - $(this).val(default_value); | |
111 | 136 | $(this).removeClass('filled-in'); |
112 | 137 | } |
113 | 138 | else $(this).addClass('filled-in'); |
114 | 139 | }); |
115 | 140 | }); |
116 | 141 | |
117 | - $('#signup-form').bind('submit', function() { | |
118 | - $('#signup-form input[type=text], #signup-form textarea').each(function() { | |
119 | - if ($(this).attr('rel')) var default_value = $(this).attr('rel').toLowerCase(); | |
120 | - if ($(this).val() == default_value) $(this).val(''); | |
121 | - }); | |
122 | - return true; | |
123 | - }); | |
124 | - | |
125 | - $('#user_password_clear, #user_password_confirmation_clear').show(); | |
126 | - $('#user_password_clear, #user_password_confirmation_clear').unbind(); | |
127 | - $('#user_pw, #user_password_confirmation').hide(); | |
128 | - $('#user_password_clear').focus(function() { | |
129 | - $(this).hide(); | |
130 | - $('#user_pw').show(); | |
131 | - $('#user_pw').focus(); | |
132 | - }); | |
133 | 142 | $('#user_pw').focus(function() { |
134 | 143 | $('#password-balloon').fadeIn('slow'); |
135 | 144 | }); |
136 | - $('#user_pw').blur(function() { | |
137 | - if ($(this).val() == '') { | |
138 | - $('#user_password_clear').show(); | |
139 | - $(this).hide(); | |
140 | - } | |
141 | - }); | |
142 | - $('#user_password_confirmation_clear').focus(function() { | |
143 | - $(this).hide(); | |
144 | - $('#user_password_confirmation').show(); | |
145 | - $('#user_password_confirmation').focus(); | |
145 | + $('#user_password_confirmation').focus(function() { | |
146 | + $('#password-confirmation-balloon').fadeIn('slow'); | |
146 | 147 | }); |
147 | 148 | $('#user_password_confirmation, #user_pw').blur(function() { |
148 | - if ($('#user_password_confirmation').val() == '') { | |
149 | - $('#user_password_confirmation_clear').show(); | |
150 | - $('#user_password_confirmation').hide(); | |
151 | - } else if ($('#user_password_confirmation').val() == $('#user_pw').val()) { | |
152 | - $('#user_password_confirmation').addClass('validated').removeClass('invalid'); | |
153 | - $('#user_pw').removeClass('invalid_input').addClass('valid_input'); | |
154 | - $('#password-check').html("<p> </p>"); | |
155 | - } else if ($('#user_password_confirmation').val() != $('#user_pw').val()) { | |
156 | - $('#user_password_confirmation').removeClass('validated').addClass('invalid'); | |
157 | - $('#user_pw').addClass('invalid_input').removeClass('valid_input'); | |
158 | - $('#password-check').html("<p><span class='invalid'><%= _('Passwords don\'t match') %></span></p>"); | |
149 | + if ($('#user_password_confirmation').val() != '') { | |
150 | + if ($('#user_password_confirmation').val() == $('#user_pw').val()) { | |
151 | + $('#user_password_confirmation').addClass('validated').removeClass('invalid'); | |
152 | + $('#user_pw').removeClass('invalid_input').addClass('valid_input'); | |
153 | + $('#password-check').html("<p> </p>"); | |
154 | + } else if ($('#user_password_confirmation').val() != $('#user_pw').val()) { | |
155 | + $('#user_password_confirmation').removeClass('validated').addClass('invalid'); | |
156 | + $('#user_pw').addClass('invalid_input').removeClass('valid_input'); | |
157 | + $('#password-check').html("<p><span class='invalid'><%= _('Passwords don\'t match') %></span></p>"); | |
158 | + } | |
159 | 159 | } |
160 | 160 | $('#password-balloon').fadeOut('slow'); |
161 | + $('#password-confirmation-balloon').fadeOut('slow'); | |
161 | 162 | }); |
162 | 163 | $('#user_login').focus(function() { |
163 | 164 | $('#signup-balloon').fadeIn('slow'); |
164 | 165 | }); |
165 | 166 | $('#user_login').blur(function() { $('#signup-balloon').fadeOut('slow'); }); |
166 | 167 | $('#signup-form').validate({ rules: { 'user[email]': { email: true } }, messages: { 'user[email]' : '' } }); |
168 | + $('#user_email').focus(function() { | |
169 | + $('#email-balloon').fadeIn('slow'); | |
170 | + }); | |
171 | + $('#user_email').blur(function() { | |
172 | + $('#email-balloon').fadeOut('slow'); | |
173 | + }); | |
174 | + $('#profile_data_name').focus(function() { | |
175 | + $('#name-balloon').fadeIn('slow'); | |
176 | + }); | |
177 | + $('#profile_data_name').blur(function() { | |
178 | + $('#name-balloon').fadeOut('slow'); | |
179 | + if ($(this).val() == '') { | |
180 | + $(this).removeClass('validated'); | |
181 | + } | |
182 | + else $(this).addClass('validated'); | |
183 | + }); | |
167 | 184 | }); |
168 | 185 | </script> | ... | ... |
app/views/account/forgot_password.rhtml
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <% labelled_form_for :change_password, @change_password, :url => { :action => 'forgot_password' } do |f| %> |
6 | 6 | |
7 | 7 | <%= f.text_field :login, |
8 | - :onchange => 'this.value = convToValidLogin( this.value )' %> | |
8 | + :onchange => 'this.value = convToValidUsername( this.value )' %> | |
9 | 9 | |
10 | 10 | <%= f.text_field :email %> |
11 | 11 | ... | ... |
app/views/admin_panel/site_info.rhtml
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | |
5 | 5 | <%= render :file => 'shared/tiny_mce' %> |
6 | 6 | |
7 | -<% labelled_form_for :environment, @environment, :url => {:host => @environment.default_hostname, :port => request.port} do |f| %> | |
7 | +<% labelled_form_for :environment, @environment do |f| %> | |
8 | 8 | <% tabs = [] %> |
9 | 9 | <% tabs << {:title => _('Site info'), :id => 'site-info', |
10 | 10 | :content => (render :partial => 'site_info', :locals => {:f => f})} %> | ... | ... |
app/views/catalog/index.rhtml
1 | 1 | <% extra_content = [] %> |
2 | 2 | <% extra_content_list = [] %> |
3 | 3 | |
4 | -<ul id="product-list"> | |
5 | - <li><h1><%= _('Products/Services') %></h1></li> | |
4 | +<h1><%= _('Products/Services') %></h1> | |
6 | 5 | |
6 | +<%= breadcrumb(@category) if params[:level] %> | |
7 | + | |
8 | +<div class='l-sidebar-left-bar'> | |
9 | + <ul> | |
10 | + <%= content_tag('li', link_to(_('Enterprise homepage'), profile.public_profile_url), :id => 'catalog-categories-homepage-link') %> | |
11 | + <% if @categories.present? %> | |
12 | + <% @categories.each do |category| %> | |
13 | + <%= category_link(category) %> | |
14 | + <%= category_sub_links(category) %> | |
15 | + <% end %> | |
16 | + <% elsif @category.present? %> | |
17 | + <%= content_tag('li', _('There are no sub-categories for %s') % @category.name, :id => 'catalog-categories-notice') %> | |
18 | + <% else %> | |
19 | + <%= content_tag('li', _('There are no categories available.'), :id => 'catalog-categories-notice') %> | |
20 | + <% end %> | |
21 | + </ul> | |
22 | +</div> | |
23 | + | |
24 | +<ul id="product-list" class="l-sidebar-left-content"> | |
7 | 25 | <% @products.each do |product| %> |
8 | 26 | <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %> |
9 | 27 | <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> |
10 | 28 | |
11 | - <li class="product <%= "not-available" unless product.available %>"> | |
29 | + <% status = [] %> | |
30 | + <% status << 'not-available' if !product.available %> | |
31 | + <% status << 'highlighted' if product.highlighted %> | |
32 | + | |
33 | + <li id="product-<%= product.id %>" class="product <%= status.join(' ') %>"> | |
12 | 34 | <ul> |
13 | 35 | <li class="product-image-link"> |
36 | + <% if product.highlighted? %> | |
37 | + <%= link_to image_tag(themed_path('/images/star.png'), :class => 'star', :alt => _('Highlighted product')), product_path(product) %> | |
38 | + <% end %> | |
14 | 39 | <% if product.image %> |
15 | 40 | <div class="zoomable-image"> |
16 | 41 | <%= link_to_product product, :class => 'product-big', :style => "background-image: url(#{product.default_image(:big)})" %> | ... | ... |
app/views/cms/_blog.rhtml
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | |
5 | 5 | <%= render :file => 'shared/tiny_mce' %> |
6 | 6 | |
7 | -<%= required f.text_field(:name, :size => '64', :onchange => "updateUrlField(this, 'article_slug')") %> | |
7 | +<%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %> | |
8 | 8 | |
9 | 9 | <%= render :partial => 'general_fields' %> |
10 | 10 | ... | ... |
app/views/cms/_event.rhtml
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | <%# TODO add Textile help here %> |
4 | 4 | <%= render :file => 'shared/tiny_mce' %> |
5 | 5 | |
6 | -<%= required f.text_field('name', :size => '64') %> | |
6 | +<%= required f.text_field('name', :size => '64', :maxlength => 150) %> | |
7 | 7 | |
8 | 8 | <%= render :partial => 'general_fields' %> |
9 | 9 | <%= render :partial => 'translatable' %> | ... | ... |
app/views/cms/_folder.rhtml
1 | 1 | <%= required_fields_message %> |
2 | 2 | |
3 | -<%= required f.text_field('name', :size => '64') %> | |
3 | +<%= required f.text_field('name', :size => '64', :maxlength => 150) %> | |
4 | 4 | <%= render :partial => 'general_fields' %> |
5 | 5 | |
6 | 6 | <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 3, :cols => 64)) %> | ... | ... |
app/views/cms/_forum.rhtml
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | |
5 | 5 | <%= render :file => 'shared/tiny_mce' %> |
6 | 6 | |
7 | -<%= required f.text_field(:name, :size => '64', :onchange => "updateUrlField(this, 'article_slug')") %> | |
7 | +<%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %> | |
8 | 8 | |
9 | 9 | <%= render :partial => 'general_fields' %> |
10 | 10 | ... | ... |
app/views/cms/_gallery.rhtml
app/views/cms/_published_article.rhtml
1 | -<%= f.text_field 'name', :size => '64' %> | |
1 | +<%= f.text_field 'name', :size => '64', :maxlength => 150 %> | |
2 | 2 | <%= render :partial => 'general_fields' %> |
3 | 3 | |
4 | 4 | <p><%= _('This is a republication of "%s", by %s.') % [link_to(h(@article.reference_article.name), @article.reference_article.url), @article.reference_article.profile.name] %></p> | ... | ... |
app/views/cms/_raw_html_article.rhtml
1 | 1 | <%= required_fields_message %> |
2 | 2 | |
3 | -<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %> | |
3 | +<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64', :maxlength => 150)) %> | |
4 | 4 | |
5 | 5 | <%= render :partial => 'general_fields' %> |
6 | 6 | <%= render :partial => 'translatable' %> | ... | ... |
app/views/cms/_textile_article.rhtml
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 | |
3 | 3 | <%# TODO add Textile help here %> |
4 | 4 | |
5 | -<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '72')) %> | |
5 | +<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '72', :maxlength => 150)) %> | |
6 | 6 | |
7 | 7 | <%= render :partial => 'general_fields' %> |
8 | 8 | <%= render :partial => 'translatable' %> | ... | ... |
app/views/cms/_tiny_mce_article.rhtml
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | <%= render :file => 'shared/tiny_mce' %> |
4 | 4 | |
5 | 5 | <div> |
6 | - <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %> | |
6 | + <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64', :maxlength => 150)) %> | |
7 | 7 | |
8 | 8 | <%= render :partial => 'general_fields' %> |
9 | 9 | <%= render :partial => 'translatable' %> | ... | ... |
app/views/cms/select_article_type.rhtml
... | ... | @@ -2,9 +2,9 @@ |
2 | 2 | |
3 | 3 | <ul id="article_types"> |
4 | 4 | <% for type in @article_types %> |
5 | - <% action = type[:name] == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:name]} %> | |
5 | + <% action = type[:class].name == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:class].name} %> | |
6 | 6 | <% content_tag('a', :href => url_for(action.merge(:parent_id => @parent_id, :back_to => @back_to))) do %> |
7 | - <li class="<%= icon_for_new_article(type[:name]) %>" onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | |
7 | + <li class="<%= icon_for_new_article(type[:class]) %>" onmouseover="javascript: jQuery(this).addClass('mouseover')" onmouseout="jQuery(this).removeClass('mouseover')"> | |
8 | 8 | <strong><%= type[:short_description] %></strong> |
9 | 9 | <div class='description'><%= type[:description] %></div> |
10 | 10 | </li> | ... | ... |
app/views/content_viewer/_article_toolbar.rhtml
... | ... | @@ -34,11 +34,11 @@ |
34 | 34 | <%= expirable_button @page, :locale, content, url %> |
35 | 35 | <% end %> |
36 | 36 | |
37 | - <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %> | |
37 | + <%= colorbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) unless remove_content_button(:new) %> | |
38 | 38 | <% end %> |
39 | 39 | |
40 | 40 | <% if @page.accept_uploads? && @page.allow_create?(user) %> |
41 | - <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) %> | |
41 | + <%= button('upload-file', _('Upload files'), profile.admin_url.merge(:controller => 'cms', :action => 'upload_files', :parent_id => (@page.folder? ? @page : @page.parent))) unless remove_content_button(:upload)%> | |
42 | 42 | <% end %> |
43 | 43 | |
44 | 44 | <% if !@page.allow_create?(user) && profile.community? && (@page.blog? || @page.parent && @page.parent.blog?) && !remove_content_button(:suggest) %> | ... | ... |
app/views/content_viewer/_comment_form.rhtml
... | ... | @@ -21,8 +21,6 @@ function submit_comment_form(button) { |
21 | 21 | } |
22 | 22 | </script> |
23 | 23 | |
24 | -<% focus_on = logged_in? ? 'title' : 'name' %> | |
25 | - | |
26 | 24 | <% if @comment && @comment.errors.any? && @comment.reply_of_id.blank? %> |
27 | 25 | <%= error_messages_for :comment %> |
28 | 26 | <script type="text/javascript">jQuery(function() { document.location.href = '#page-comment-form'; });</script> |
... | ... | @@ -32,17 +30,7 @@ function submit_comment_form(button) { |
32 | 30 | |
33 | 31 | <div class="post_comment_box <%= @form_div %>"> |
34 | 32 | |
35 | -<% if display_link %> | |
36 | - <h4 onclick="var d = jQuery(this).parent('.post_comment_box'); | |
37 | - if (d.hasClass('closed')) { | |
38 | - d.removeClass('closed'); | |
39 | - d.addClass('opened'); | |
40 | - d.find('input[name=comment[title]], textarea').val(''); | |
41 | - d.find('.comment_form input[name=comment[<%= focus_on %>]]').focus(); | |
42 | - }"> | |
43 | - <%= content_tag('a', '', :name => 'comment_form') + _('Post a comment') %> | |
44 | - </h4> | |
45 | -<% end %> | |
33 | + <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form') if display_link %> | |
46 | 34 | |
47 | 35 | <% unless pass_without_comment_captcha? %> |
48 | 36 | <div id="recaptcha-container" style="display: none"> |
... | ... | @@ -62,8 +50,6 @@ function submit_comment_form(button) { |
62 | 50 | <% end %> |
63 | 51 | |
64 | 52 | <% form_tag( url, { :class => 'comment_form' } ) do %> |
65 | - <%= hidden_field_tag(:confirm, 'false') %> | |
66 | - | |
67 | 53 | <%= required_fields_message %> |
68 | 54 | |
69 | 55 | <% unless logged_in? %> |
... | ... | @@ -84,10 +70,13 @@ function submit_comment_form(button) { |
84 | 70 | <%= labelled_form_field(_('Title'), text_field(:comment, :title)) %> |
85 | 71 | <%= required labelled_form_field(_('Enter your comment'), text_area(:comment, :body, :rows => 5)) %> |
86 | 72 | |
73 | + <%= hidden_field_tag(:confirm, 'false') %> | |
74 | + <%= hidden_field_tag(:view, params[:view])%> | |
75 | + | |
87 | 76 | <% button_bar do %> |
88 | 77 | <%= submit_button('add', _('Post comment'), :onclick => "submit_comment_form(this); return false") %> |
89 | 78 | <% if cancel_triggers_hide %> |
90 | - <%= button_to_function :cancel, _('Cancel'), "f=jQuery(this).parents('.post_comment_box'); f.removeClass('opened'); f.addClass('closed'); return false" %> | |
79 | + <%= button :cancel, _('Cancel'), '', :id => 'cancel-comment' %> | |
91 | 80 | <% else %> |
92 | 81 | <%= button('cancel', _('Cancel'), {:action => 'view_page', :profile => profile.identifier, :page => @comment.article.explode_path})%> |
93 | 82 | <% end %> |
... | ... | @@ -95,3 +84,5 @@ function submit_comment_form(button) { |
95 | 84 | <% end %> |
96 | 85 | |
97 | 86 | </div><!-- end class="post_comment_box" --> |
87 | + | |
88 | +<%= javascript_include_tag 'comment_form'%> | ... | ... |
app/views/content_viewer/view_page.rhtml
... | ... | @@ -90,7 +90,7 @@ |
90 | 90 | <% end %> |
91 | 91 | |
92 | 92 | <% if @page.accept_comments? && @comments_count > 1 %> |
93 | - <p class="post-comment-button"><a href="#comment_form" onclick="jQuery('#page-comment-form h4').first().trigger('click')"><%= _('Post a comment') %></a></p> | |
93 | + <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form') %> | |
94 | 94 | <% end %> |
95 | 95 | |
96 | 96 | <ul class="article-comments-list"> | ... | ... |
app/views/layouts/application-ng.rhtml
... | ... | @@ -69,7 +69,7 @@ |
69 | 69 | <% end %> |
70 | 70 | |
71 | 71 | </span> |
72 | - <form action="/search" class="search_form" method="get" class="clean"> | |
72 | + <form action="/search" class="search_form clean" method="get" id="top-search"> | |
73 | 73 | <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> |
74 | 74 | <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div> |
75 | 75 | <%= javascript_tag 'jQuery("#user form input").hint();' %> | ... | ... |
app/views/profile/_create_article.rhtml
... | ... | @@ -9,7 +9,7 @@ |
9 | 9 | <div class='profile-activity-lead'> |
10 | 10 | <div class='article-name'><%= link_to(activity.params['name'], activity.params['url']) %></div> |
11 | 11 | <span title='<%= activity.target.class.short_description %>' class='profile-activity-icon icon-new icon-new<%= activity.target.class.icon_name %>'></span> |
12 | - <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xA0|\xC2|\s)+/, ' ').gsub(/^\s+/, '') %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small> | |
12 | + <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small> | |
13 | 13 | </div> |
14 | 14 | <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %> |
15 | 15 | <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> | ... | ... |
app/views/profile/communities.rhtml
app/views/profile_editor/_person_form.rhtml
... | ... | @@ -21,6 +21,8 @@ |
21 | 21 | <%= optional_field(@person, 'city', f.text_field(:city, :rel => _('City'))) %> |
22 | 22 | <%= optional_field(@person, 'zip_code', labelled_form_field(_('ZIP code'), text_field(:profile_data, :zip_code, :rel => _('ZIP code')))) %> |
23 | 23 | <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> |
24 | +<%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %> | |
25 | +<%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %> | |
24 | 26 | |
25 | 27 | <% optional_field(@person, 'schooling') do %> |
26 | 28 | <div class="formfieldline"> | ... | ... |
app/views/search/_image.rhtml
... | ... | @@ -28,8 +28,9 @@ |
28 | 28 | <div class="search-gallery-items"> |
29 | 29 | <% r = image.children.find(:all, :order => :updated_at, :conditions => ['type = ?', 'UploadedFile']).last(3) %> |
30 | 30 | <% if r.length > 0 %> |
31 | - <% r.each do |i| %> | |
32 | - <%= link_to '', i.view_url, :class => "search-image-pic", :style => 'background-image: url(%s)'% i.public_filename(:thumb) %> | |
31 | + <% r.each_index do |i| img = r[i] %> | |
32 | + <%= link_to '', img.view_url, :class => "search-image-pic pic-num#{i+1}", | |
33 | + :style => 'background-image: url(%s)'% img.public_filename(:thumb) %> | |
33 | 34 | <% end %> |
34 | 35 | <% else %> |
35 | 36 | <div class="search-no-image"><span><%= _('No image') %></span></div> | ... | ... |
app/views/search/_product.rhtml
1 | -<% extra_content = @plugins.dispatch(:asset_product_extras, product, product.enterprise).collect { |content| instance_eval(&content) } %> | |
1 | +<% extra_content = @plugins.dispatch(:asset_product_extras, product).collect { |content| instance_eval(&content) } %> | |
2 | 2 | <% extra_properties = @plugins.dispatch(:asset_product_properties, product)%> |
3 | 3 | |
4 | -<li class="search-product-item"> | |
4 | +<li class="search-product-item <%= 'highlighted' if product.highlighted? %>"> | |
5 | 5 | |
6 | 6 | <div class="search-product-item-first-column"> |
7 | 7 | <%= render :partial => 'search/image', :object => product %> | ... | ... |
app/views/shared/_organization_custom_fields.rhtml
... | ... | @@ -10,6 +10,8 @@ |
10 | 10 | <%= optional_field(profile, 'economic_activity', f.text_field(:economic_activity)) %> |
11 | 11 | <%= optional_field(profile, 'management_information', f.text_area(:management_information, :rows => 5)) %> |
12 | 12 | <%= optional_field(profile, 'address', labelled_form_field(_('Address (street and number)'), text_field(object_name, :address))) %> |
13 | +<%= optional_field(profile, 'address_reference', labelled_form_field(_('Address reference'), text_field(object_name, :address_reference))) %> | |
14 | +<%= optional_field(profile, 'district', labelled_form_field(_('District'), text_field(object_name, :district))) %> | |
13 | 15 | <%= optional_field(profile, 'zip_code', labelled_form_field(_('ZIP code'), text_field(object_name, :zip_code))) %> |
14 | 16 | <%= optional_field(profile, 'city', f.text_field(:city)) %> |
15 | 17 | <%= optional_field(profile, 'state', f.text_field(:state)) %> | ... | ... |
app/views/shared/tiny_mce.rhtml
... | ... | @@ -20,7 +20,7 @@ tinyMCE.init({ |
20 | 20 | editor_selector : "mceEditor", |
21 | 21 | theme : "advanced", |
22 | 22 | relative_urls : false, |
23 | - remove_script_host : true, | |
23 | + remove_script_host : false, | |
24 | 24 | document_base_url : <%= environment.top_url.to_json %>, |
25 | 25 | plugins: myplugins, |
26 | 26 | theme_advanced_toolbar_location : "top", | ... | ... |
app/views/users/send_mail.rhtml
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | |
5 | 5 | <%= render :file => 'shared/tiny_mce' %> |
6 | 6 | |
7 | -<% form_for :mailing, :url => {:action => 'send_mail', :host => @environment.default_hostname} do |f| %> | |
7 | +<% form_for :mailing do |f| %> | |
8 | 8 | <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> |
9 | 9 | <%= labelled_form_field(_('Body:'), f.text_area(:body, :class => 'mceEditor')) %> |
10 | 10 | <%= submit_button(:send, _('Send')) %> | ... | ... |
config/cucumber.yml
1 | -default: --tags ~@selenium,~@wip --exclude features/support/selenium.rb --exclude features/step_definitions/selenium_steps.rb -r features/support -r features/step_definitions | |
2 | -selenium: --tags @selenium,~@wip -r features/support -r features/step_definitions | |
1 | +default: --color --format progress --strict --tags ~@selenium --tags ~@selenium-fixme --tags ~@fixme --exclude features/support/selenium.rb -r features/support -r features/step_definitions | |
2 | +selenium: --strict --tags @selenium -r features/support -r features/step_definitions | ... | ... |
config/database.yml.sqlite3
config/environments/cucumber.rb
1 | -# IMPORTANT: This file was generated by Cucumber 0.4.0 | |
2 | 1 | # Edit at your own peril - it's recommended to regenerate this file |
3 | 2 | # in the future when you upgrade to a newer version of Cucumber. |
4 | 3 | |
5 | -config.cache_classes = true # This must be true for Cucumber to operate correctly! | |
4 | +# IMPORTANT: Setting config.cache_classes to false is known to | |
5 | +# break Cucumber's use_transactional_fixtures method. | |
6 | +# For more information see https://rspec.lighthouseapp.com/projects/16211/tickets/165 | |
7 | +config.cache_classes = true | |
6 | 8 | |
7 | 9 | # Log error messages when you accidentally call methods on nil. |
8 | 10 | config.whiny_nils = true |
... | ... | @@ -18,3 +20,8 @@ config.action_controller.allow_forgery_protection = false |
18 | 20 | # The :test delivery method accumulates sent emails in the |
19 | 21 | # ActionMailer::Base.deliveries array. |
20 | 22 | config.action_mailer.delivery_method = :test |
23 | + | |
24 | +config.gem 'cucumber-rails', :lib => false, :version => '>=0.3.2' unless File.directory?(File.join(Rails.root, 'vendor/plugins/cucumber-rails')) | |
25 | +config.gem 'database_cleaner', :lib => false, :version => '>=0.5.0' unless File.directory?(File.join(Rails.root, 'vendor/plugins/database_cleaner')) | |
26 | +config.gem 'capybara', :lib => false, :version => '>=0.3.5' unless File.directory?(File.join(Rails.root, 'vendor/plugins/capybara')) | |
27 | + | ... | ... |
config/initializers/plugins.rb
db/migrate/20130111232201_aggressive_indexing_strategy3.rb
0 → 100644
... | ... | @@ -0,0 +1,39 @@ |
1 | +class AggressiveIndexingStrategy3 < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + add_index :articles, :slug | |
4 | + add_index :articles, :parent_id | |
5 | + add_index :articles, :profile_id | |
6 | + add_index :articles, :name | |
7 | + | |
8 | + add_index :article_versions, :article_id | |
9 | + | |
10 | + add_index :comments, [:source_id, :spam] | |
11 | + | |
12 | + add_index :profiles, :identifier | |
13 | + | |
14 | + add_index :friendships, :person_id | |
15 | + add_index :friendships, :friend_id | |
16 | + add_index :friendships, [:person_id, :friend_id], :uniq => true | |
17 | + | |
18 | + add_index :external_feeds, :blog_id | |
19 | + end | |
20 | + | |
21 | + def self.down | |
22 | + remove_index :articles, :slug | |
23 | + remove_index :articles, :parent_id | |
24 | + remove_index :articles, :profile_id | |
25 | + remove_index :articles, :name | |
26 | + | |
27 | + remove_index :article_versions, :article_id | |
28 | + | |
29 | + remove_index :comments, [:source_id, :spam] | |
30 | + | |
31 | + remove_index :profiles, :identifier | |
32 | + | |
33 | + remove_index :friendships, :person_id | |
34 | + remove_index :friendships, :friend_id | |
35 | + remove_index :friendships, [:person_id, :friend_id] | |
36 | + | |
37 | + remove_index :external_feeds, :blog_id | |
38 | + end | |
39 | +end | ... | ... |
db/migrate/20130117132943_remove_index_articles_on_name.rb
0 → 100644
db/migrate/20130304200849_add_default_value_to_product_highlighted.rb
0 → 100644
... | ... | @@ -0,0 +1,10 @@ |
1 | +class AddDefaultValueToProductHighlighted < ActiveRecord::Migration | |
2 | + def self.up | |
3 | + change_column :products, :highlighted, :boolean, :default => false | |
4 | + execute('UPDATE products SET highlighted=(0>1) WHERE highlighted IS NULL;') | |
5 | + end | |
6 | + | |
7 | + def self.down | |
8 | + say 'This migraiton is not reversible!' | |
9 | + end | |
10 | +end | ... | ... |
db/schema.rb
... | ... | @@ -9,7 +9,7 @@ |
9 | 9 | # |
10 | 10 | # It's strongly recommended to check this file into your version control system. |
11 | 11 | |
12 | -ActiveRecord::Schema.define(:version => 20121008185303) do | |
12 | +ActiveRecord::Schema.define(:version => 20130304200849) do | |
13 | 13 | |
14 | 14 | create_table "abuse_reports", :force => true do |t| |
15 | 15 | t.integer "reporter_id" |
... | ... | @@ -88,6 +88,8 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
88 | 88 | t.integer "license_id" |
89 | 89 | end |
90 | 90 | |
91 | + add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id" | |
92 | + | |
91 | 93 | create_table "articles", :force => true do |t| |
92 | 94 | t.string "name" |
93 | 95 | t.string "slug" |
... | ... | @@ -129,6 +131,10 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
129 | 131 | t.integer "license_id" |
130 | 132 | end |
131 | 133 | |
134 | + add_index "articles", ["name"], :name => "index_articles_on_name" | |
135 | + add_index "articles", ["parent_id"], :name => "index_articles_on_parent_id" | |
136 | + add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id" | |
137 | + add_index "articles", ["slug"], :name => "index_articles_on_slug" | |
132 | 138 | add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id" |
133 | 139 | |
134 | 140 | create_table "articles_categories", :id => false, :force => true do |t| |
... | ... | @@ -217,6 +223,8 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
217 | 223 | t.string "referrer" |
218 | 224 | end |
219 | 225 | |
226 | + add_index "comments", ["source_id", "spam"], :name => "index_comments_on_source_id_and_spam" | |
227 | + | |
220 | 228 | create_table "contact_lists", :force => true do |t| |
221 | 229 | t.text "list" |
222 | 230 | t.string "error_fetching" |
... | ... | @@ -280,6 +288,7 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
280 | 288 | t.integer "update_errors", :default => 0 |
281 | 289 | end |
282 | 290 | |
291 | + add_index "external_feeds", ["blog_id"], :name => "index_external_feeds_on_blog_id" | |
283 | 292 | add_index "external_feeds", ["enabled"], :name => "index_external_feeds_on_enabled" |
284 | 293 | add_index "external_feeds", ["fetched_at"], :name => "index_external_feeds_on_fetched_at" |
285 | 294 | |
... | ... | @@ -295,6 +304,10 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
295 | 304 | t.string "group" |
296 | 305 | end |
297 | 306 | |
307 | + add_index "friendships", ["friend_id"], :name => "index_friendships_on_friend_id" | |
308 | + add_index "friendships", ["person_id", "friend_id"], :name => "index_friendships_on_person_id_and_friend_id" | |
309 | + add_index "friendships", ["person_id"], :name => "index_friendships_on_person_id" | |
310 | + | |
298 | 311 | create_table "images", :force => true do |t| |
299 | 312 | t.integer "parent_id" |
300 | 313 | t.string "content_type" |
... | ... | @@ -402,7 +415,7 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
402 | 415 | t.datetime "updated_at" |
403 | 416 | t.decimal "discount" |
404 | 417 | t.boolean "available", :default => true |
405 | - t.boolean "highlighted" | |
418 | + t.boolean "highlighted", :default => false | |
406 | 419 | t.integer "unit_id" |
407 | 420 | t.integer "image_id" |
408 | 421 | end |
... | ... | @@ -446,6 +459,7 @@ ActiveRecord::Schema.define(:version => 20121008185303) do |
446 | 459 | end |
447 | 460 | |
448 | 461 | add_index "profiles", ["environment_id"], :name => "index_profiles_on_environment_id" |
462 | + add_index "profiles", ["identifier"], :name => "index_profiles_on_identifier" | |
449 | 463 | add_index "profiles", ["region_id"], :name => "index_profiles_on_region_id" |
450 | 464 | |
451 | 465 | create_table "qualifier_certifiers", :force => true do |t| | ... | ... |
debian/changelog
1 | +noosfero (0.41.1) unstable; urgency=low | |
2 | + | |
3 | + * Bugfixes release | |
4 | + | |
5 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Fri, 08 Mar 2013 11:33:11 -0300 | |
6 | + | |
7 | +noosfero (0.41.0) unstable; urgency=low | |
8 | + | |
9 | + * Features version with anti spam-bot measures | |
10 | + | |
11 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Mon, 28 Jan 2013 10:20:21 +0000 | |
12 | + | |
13 | +noosfero (0.40.0) unstable; urgency=low | |
14 | + | |
15 | + * Features version release | |
16 | + | |
17 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Sat, 19 Jan 2013 21:58:06 +0000 | |
18 | + | |
19 | +noosfero (0.39.3) unstable; urgency=low | |
20 | + | |
21 | + * Bugfixes release | |
22 | + | |
23 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Sat, 19 Jan 2013 19:27:04 +0000 | |
24 | + | |
25 | +noosfero (0.39.2) unstable; urgency=low | |
26 | + | |
27 | + * Bugfixes release | |
28 | + | |
29 | + -- Rodrigo Souto <rodrigo@colivre.coop.br> Sat, 12 Jan 2013 10:13:46 +0000 | |
30 | + | |
31 | +noosfero (0.39.1) unstable; urgency=low | |
32 | + | |
33 | + * Bugfixes release | |
34 | + | |
35 | + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Thu, 20 Dec 2012 15:47:55 -0200 | |
36 | + | |
37 | +noosfero (0.39.0) unstable; urgency=low | |
38 | + | |
39 | + * Features version release | |
40 | + | |
41 | + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Fri, 07 Dec 2012 09:53:42 -0200 | |
42 | + | |
1 | 43 | noosfero (0.39.0~1) UNRELEASED; urgency=low |
2 | 44 | |
3 | 45 | * Pre-release to test the antispam mechanism. | ... | ... |
debian/noosfero.install
... | ... | @@ -32,6 +32,8 @@ debian/solr.yml etc/noosfero |
32 | 32 | debian/thin.yml etc/noosfero |
33 | 33 | etc/logrotate.d/noosfero etc/logrotate.d |
34 | 34 | debian/noosfero.yml etc/noosfero |
35 | +etc/noosfero/varnish-accept-language.vcl etc/noosfero | |
36 | +etc/noosfero/varnish-noosfero.vcl etc/noosfero | |
35 | 37 | |
36 | 38 | locale usr/share/noosfero |
37 | 39 | doc/noosfero usr/share/noosfero/doc | ... | ... |
etc/noosfero/varnish-noosfero.vcl
1 | 1 | sub vcl_recv { |
2 | 2 | if (req.request == "GET" || req.request == "HEAD") { |
3 | 3 | if (req.http.Cookie) { |
4 | - # We only care about the "_noosfero_session.*" cookie, used for | |
5 | - # authentication. | |
6 | - if (req.http.Cookie !~ "_noosfero_session.*" ) { | |
4 | + # We only care about the "_noosfero_.*" cookies, used by Noosfero | |
5 | + if (req.http.Cookie !~ "_noosfero_.*" ) { | |
7 | 6 | # strip all cookies |
8 | 7 | unset req.http.Cookie; |
9 | 8 | } | ... | ... |
features/accept_member.feature
... | ... | @@ -14,10 +14,11 @@ Feature: accept member |
14 | 14 | And the community "My Community" is closed |
15 | 15 | And "Mario Souto" is admin of "My Community" |
16 | 16 | |
17 | + @selenium | |
17 | 18 | Scenario: approve a task to accept a member as admin in a closed community |
18 | 19 | Given "Marie Curie" asked to join "My Community" |
19 | 20 | And I am logged in as "mario" |
20 | - And I go to My Community's control panel | |
21 | + And I go to mycommunity's control panel | |
21 | 22 | And I follow "Process requests" |
22 | 23 | And I should see "Marie Curie wants to be a member" |
23 | 24 | When I choose "Accept" |
... | ... | @@ -25,10 +26,11 @@ Feature: accept member |
25 | 26 | And I press "Apply!" |
26 | 27 | Then "Marie Curie" should be admin of "My Community" |
27 | 28 | |
29 | + @selenium | |
28 | 30 | Scenario: approve a task to accept a member as member in a closed community |
29 | 31 | Given "Marie Curie" asked to join "My Community" |
30 | 32 | And I am logged in as "mario" |
31 | - And I go to My Community's control panel | |
33 | + And I go to mycommunity's control panel | |
32 | 34 | And I follow "Process requests" |
33 | 35 | And I should see "Marie Curie wants to be a member" |
34 | 36 | When I choose "Accept" |
... | ... | @@ -36,10 +38,11 @@ Feature: accept member |
36 | 38 | And I press "Apply!" |
37 | 39 | Then "Marie Curie" should be a member of "My Community" |
38 | 40 | |
41 | + @selenium | |
39 | 42 | Scenario: approve a task to accept a member as moderator in a closed community |
40 | 43 | Given "Marie Curie" asked to join "My Community" |
41 | 44 | And I am logged in as "mario" |
42 | - And I go to My Community's control panel | |
45 | + And I go to mycommunity's control panel | |
43 | 46 | And I follow "Process requests" |
44 | 47 | And I should see "Marie Curie wants to be a member" |
45 | 48 | When I choose "Accept" | ... | ... |
features/activate_enterprise.feature
... | ... | @@ -11,7 +11,7 @@ Feature: activate enterprise |
11 | 11 | |
12 | 12 | Scenario: added an unexistent code |
13 | 13 | Given feature "enterprise_activation" is enabled on environment |
14 | - And I am on Joao Silva's control panel | |
14 | + And I am on joaosilva's control panel | |
15 | 15 | And I fill in "Enterprise activation code" with "abcde" |
16 | 16 | When I press "Activate" |
17 | 17 | Then I should see "Invalid enterprise code" |
... | ... | @@ -21,7 +21,7 @@ Feature: activate enterprise |
21 | 21 | And the following enterprises |
22 | 22 | | identifier | name | enabled | |
23 | 23 | | products-factory | Products Factory | false | |
24 | - And I am on Joao Silva's control panel | |
24 | + And I am on joaosilva's control panel | |
25 | 25 | And enterprise "Products Factory" is enabled |
26 | 26 | And I fill in "Enterprise activation code" with code of "Products Factory" |
27 | 27 | When I press "Activate" |
... | ... | @@ -32,7 +32,7 @@ Feature: activate enterprise |
32 | 32 | And the following enterprises |
33 | 33 | | identifier | name | enabled | |
34 | 34 | | products-factory | Products Factory | false | |
35 | - And I am on Joao Silva's control panel | |
35 | + And I am on joaosilva's control panel | |
36 | 36 | And I fill in "Enterprise activation code" with code of "Products Factory" |
37 | 37 | When I press "Activate" |
38 | 38 | Then I should see "We don't have enough information about your enterprise to identify you." |
... | ... | @@ -43,7 +43,7 @@ Feature: activate enterprise |
43 | 43 | And the following enterprises |
44 | 44 | | identifier | name | enabled | foundation_year | |
45 | 45 | | services-provider | Services Provider | false | 2000 | |
46 | - And I am on Joao Silva's control panel | |
46 | + And I am on joaosilva's control panel | |
47 | 47 | And I fill in "Enterprise activation code" with code of "Services Provider" |
48 | 48 | And I press "Activate" |
49 | 49 | And I fill in "What year your enterprise was founded? It must have 4 digits, eg 1990." with "1999" |
... | ... | @@ -56,7 +56,7 @@ Feature: activate enterprise |
56 | 56 | And the following enterprises |
57 | 57 | | identifier | name | enabled | cnpj | |
58 | 58 | | services-provider | Services Provider | false | 94.132.024/0001-48 | |
59 | - And I am on Joao Silva's control panel | |
59 | + And I am on joaosilva's control panel | |
60 | 60 | And I fill in "Enterprise activation code" with code of "Services Provider" |
61 | 61 | And I press "Activate" |
62 | 62 | And I fill in "What is the CNPJ of your enterprise?" with "12345678912345" |
... | ... | @@ -70,9 +70,9 @@ Feature: activate enterprise |
70 | 70 | And the following enterprises |
71 | 71 | | identifier | name | enabled | foundation_year | |
72 | 72 | | services-provider | Services Provider | false | 2000 | |
73 | - And I visit "Joao Silva's control panel" and wait | |
73 | + And I go to joaosilva's control panel | |
74 | 74 | And I fill in "Enterprise activation code" with code of "Services Provider" |
75 | - And I press "Activate" and wait | |
75 | + And I press "Activate" | |
76 | 76 | And I fill in "What year your enterprise was founded? It must have 4 digits, eg 1990." with "2000" |
77 | 77 | And I press "Continue" |
78 | 78 | And I check "I read the terms of use and accepted them" |
... | ... | @@ -91,9 +91,9 @@ Feature: activate enterprise |
91 | 91 | | active-template | Active Template | false | 2000 | |
92 | 92 | And "Active Template" is the active enterprise template |
93 | 93 | And "Services Provider 2" doesnt have "Active Template" as template |
94 | - And I visit "Joao Silva's control panel" and wait | |
94 | + And I go to joaosilva's control panel | |
95 | 95 | And I fill in "Enterprise activation code" with code of "Services Provider 2" |
96 | - And I press "Activate" and wait | |
96 | + And I press "Activate" | |
97 | 97 | And I fill in "What year your enterprise was founded? It must have 4 digits, eg 1990." with "2000" |
98 | 98 | And I press "Continue" |
99 | 99 | And I check "I read the terms of use and accepted them" |
... | ... | @@ -113,9 +113,9 @@ Feature: activate enterprise |
113 | 113 | | active-template | Active Template | false | 2000 | |
114 | 114 | And "Active Template" is the active enterprise template |
115 | 115 | And "Services Provider 3" doesnt have "Active Template" as template |
116 | - When I visit "Joao Silva's control panel" and wait | |
116 | + When I go to joaosilva's control panel | |
117 | 117 | And I fill in "Enterprise activation code" with code of "Services Provider 3" |
118 | - And I press "Activate" and wait | |
118 | + And I press "Activate" | |
119 | 119 | And I fill in "What year your enterprise was founded? It must have 4 digits, eg 1990." with "2000" |
120 | 120 | And I press "Continue" |
121 | 121 | And I check "I read the terms of use and accepted them" | ... | ... |
features/admin_categories.feature
... | ... | @@ -16,22 +16,22 @@ Feature: manage categories |
16 | 16 | @selenium |
17 | 17 | Scenario: admin user could access new category |
18 | 18 | Given I follow "Administration" |
19 | - When I follow "Manage Categories" | |
20 | - And I follow "New category" and wait | |
19 | + When I follow "Categories" | |
20 | + And I follow "New category" | |
21 | 21 | Then I should be on /admin/categories/new |
22 | 22 | |
23 | 23 | @selenium |
24 | 24 | Scenario: admin user could create a category |
25 | - Given I visit "/admin/categories/new" and wait | |
26 | - When I fill in "Name" with "Category 1" | |
27 | - And I press "Save" | |
28 | - Then I should see "Categories" | |
29 | - And I should see "Category 1" | |
25 | + Given I go to /admin/categories/new | |
26 | + And I fill in "Name" with "Category 1" | |
27 | + When I press "Save" | |
28 | + Then I should see "Categories" | |
29 | + And I should see "Category 1" | |
30 | 30 | |
31 | 31 | @selenium |
32 | 32 | Scenario: admin user could see all the category tree |
33 | 33 | Given I follow "Administration" |
34 | - And I follow "Manage Categories" | |
34 | + And I follow "Categories" | |
35 | 35 | When I follow "Show" |
36 | 36 | Then I should see "Vegetarian" |
37 | 37 | And I should see "Steak" |
... | ... | @@ -39,13 +39,13 @@ Feature: manage categories |
39 | 39 | @selenium |
40 | 40 | Scenario: admin user could hide the category tree |
41 | 41 | Given I follow "Administration" |
42 | - And I follow "Manage Categories" | |
43 | - When I follow "Show" | |
42 | + And I follow "Categories" | |
43 | + When I follow "Show" and wait while it hides | |
44 | 44 | Then I should see "Vegetarian" |
45 | 45 | And I should see "Steak" |
46 | - When I follow "Hide" and sleep 1 second | |
47 | - Then I should not see "Vegetarian" | |
48 | - And I should not see "Steak" | |
46 | + When I follow "Hide" and wait while it hides | |
47 | + Then "Vegetarian" should not be visible within "div" | |
48 | + And "Steak" should not be visible within "div" | |
49 | 49 | |
50 | 50 | @selenium |
51 | 51 | Scenario: the show link is available just for categories with category tree |
... | ... | @@ -54,7 +54,7 @@ Feature: manage categories |
54 | 54 | | Steak | Pig | true | |
55 | 55 | And I am on the homepage |
56 | 56 | When I follow "Administration" |
57 | - And I follow "Manage Categories" | |
57 | + And I follow "Categories" | |
58 | 58 | Then I should see "Food Show" |
59 | 59 | When I follow "Show" |
60 | 60 | Then I should see "Vegetarian" | ... | ... |
features/approve_article.feature
... | ... | @@ -19,52 +19,52 @@ Feature: approve article |
19 | 19 | And "Maria Silva" is a member of "Sample Community" |
20 | 20 | And "Joao Silva" is admin of "Sample Community" |
21 | 21 | |
22 | - @selenium | |
22 | + @selenium-fixme | |
23 | 23 | Scenario: edit an article before approval |
24 | 24 | Given I am logged in as "mariasilva" |
25 | - And I am on Maria Silva's homepage | |
26 | - When I follow "Spread" and wait | |
25 | + And I am on mariasilva's homepage | |
26 | + When I follow "Spread" | |
27 | 27 | And I check "Sample Community" |
28 | 28 | And I press "Spread this" |
29 | 29 | And I am logged in as "joaosilva" |
30 | - And I go to Sample Community's control panel | |
31 | - And I follow "Process requests" and wait | |
30 | + And I go to sample-community's control panel | |
31 | + And I follow "Process requests" | |
32 | 32 | And I fill in "Text" with "This is an article edited" |
33 | 33 | And I choose "Accept" |
34 | 34 | And I press "Apply!" |
35 | - And I go to Sample Community's sitemap | |
35 | + And I go to sample-community's sitemap | |
36 | 36 | And I follow "Sample Article" |
37 | 37 | Then I should see "This is an article edited" |
38 | 38 | |
39 | 39 | @selenium |
40 | 40 | Scenario: reject an article with explanation |
41 | 41 | Given I am logged in as "mariasilva" |
42 | - And I go to Maria Silva's cms | |
42 | + And I go to mariasilva's cms | |
43 | 43 | And I follow "Sample Article" |
44 | - And I follow "Spread" and wait | |
44 | + And I follow "Spread" | |
45 | 45 | And I check "Sample Community" |
46 | 46 | And I press "Spread this" |
47 | 47 | And I am logged in as "joaosilva" |
48 | - And I go to Sample Community's control panel | |
49 | - And I follow "Process requests" and wait | |
48 | + And I go to sample-community's control panel | |
49 | + And I follow "Process requests" | |
50 | 50 | And I choose "Reject" |
51 | 51 | And I fill in "Rejection explanation" with "This is not an appropriate article for this community." |
52 | 52 | And I press "Apply!" |
53 | - When I go to Sample Community's sitemap | |
53 | + When I go to sample-community's sitemap | |
54 | 54 | Then I should not see "Sample Article" |
55 | 55 | |
56 | 56 | @selenium |
57 | 57 | Scenario: reject an article that was removed |
58 | 58 | Given I am logged in as "mariasilva" |
59 | 59 | And I follow "Dub Wars" |
60 | - And I follow "Spread" and wait | |
60 | + And I follow "Spread" | |
61 | 61 | And I check "Sample Community" |
62 | 62 | And I press "Spread this" |
63 | 63 | And I follow "Delete" |
64 | - And I press "Yes, I want." | |
64 | + And I confirm the browser dialog | |
65 | 65 | When I am logged in as "joaosilva" |
66 | - And I go to Sample Community's control panel | |
67 | - And I follow "Process requests" and wait | |
66 | + And I go to sample-community's control panel | |
67 | + And I follow "Process requests" | |
68 | 68 | And I choose "Reject" |
69 | 69 | And I fill in "Rejection explanation" with "Article was removed." |
70 | 70 | And I press "Apply!" | ... | ... |
features/balloon.feature
... | ... | @@ -12,33 +12,29 @@ Feature: balloon |
12 | 12 | @selenium |
13 | 13 | Scenario: I should not see trigger if not enabled |
14 | 14 | Given feature "show_balloon_with_profile_links_when_clicked" is disabled on environment |
15 | - When I go to /browse/people | |
15 | + When I go to /search/people | |
16 | 16 | Then I should not see "Profile links" |
17 | 17 | |
18 | 18 | @selenium |
19 | 19 | Scenario: I should not see trigger by default |
20 | - Given the following blocks | |
21 | - | owner | type | | |
22 | - | environment | PeopleBlock | | |
23 | - And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | |
24 | - When I go to the homepage | |
20 | + Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | |
21 | + When I go to /search/people | |
25 | 22 | Then I should not see "Friends" |
26 | 23 | |
27 | 24 | @selenium |
28 | 25 | Scenario: I should see balloon when clicked on people block trigger |
29 | - Given the following blocks | |
30 | - | owner | type | | |
31 | - | environment | PeopleBlock | | |
32 | - And feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | |
33 | - When I go to the homepage | |
34 | - And I follow "Profile links" | |
26 | + Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment | |
27 | + And I go to /search/people | |
28 | + And display ".person-trigger" | |
29 | + When I follow "Profile links" | |
35 | 30 | Then I should see "Friends" |
36 | 31 | |
37 | 32 | @selenium |
38 | 33 | Scenario: I should see balloon when clicked on community block trigger |
39 | 34 | Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment |
40 | - When I go to /browse/communities | |
41 | - And I follow "Profile links" | |
35 | + And I go to /search/communities | |
36 | + And display ".community-trigger" | |
37 | + When I follow "Profile links" | |
42 | 38 | Then I should see "Members" |
43 | 39 | |
44 | 40 | @selenium |
... | ... | @@ -56,7 +52,8 @@ Feature: balloon |
56 | 52 | @selenium |
57 | 53 | Scenario: I should see balloon when clicked on page trigger |
58 | 54 | Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment |
59 | - When I go to /assets/communities | |
60 | - And I follow "Profile links" | |
55 | + And I go to /assets/communities | |
56 | + And display ".community-trigger" | |
57 | + When I follow "Profile links" | |
61 | 58 | Then I should see "Members" |
62 | 59 | And I should see "Agenda" | ... | ... |
features/blog.feature
... | ... | @@ -11,16 +11,16 @@ Feature: blog |
11 | 11 | And I am logged in as "joaosilva" |
12 | 12 | |
13 | 13 | Scenario: create a blog |
14 | - Given I go to the Control panel | |
14 | + Given I go to joaosilva's control panel | |
15 | 15 | And I follow "Create blog" |
16 | 16 | Then I should see "My Blog" |
17 | 17 | When I fill in "Title" with "My Blog" |
18 | 18 | And I press "Save" |
19 | - And I go to Joao Silva's control panel | |
19 | + And I go to joaosilva's control panel | |
20 | 20 | Then I should see "Configure blog" |
21 | 21 | |
22 | 22 | Scenario: redirect to blog after create blog from control panel |
23 | - Given I go to the Control panel | |
23 | + Given I go to joaosilva's control panel | |
24 | 24 | And I follow "Create blog" |
25 | 25 | Then I should see "My Blog" |
26 | 26 | When I fill in "Title" with "My Blog" |
... | ... | @@ -28,7 +28,7 @@ Feature: blog |
28 | 28 | Then I should be on /joaosilva/my-blog |
29 | 29 | |
30 | 30 | Scenario: redirect to blog after create blog from cms |
31 | - Given I go to the Control panel | |
31 | + Given I go to joaosilva's control panel | |
32 | 32 | And I follow "Manage Content" |
33 | 33 | And I follow "New content" |
34 | 34 | When I follow "Blog" |
... | ... | @@ -37,13 +37,13 @@ Feature: blog |
37 | 37 | Then I should be on /joaosilva/blog-from-cms |
38 | 38 | |
39 | 39 | Scenario: create multiple blogs |
40 | - Given I go to the Control panel | |
40 | + Given I go to joaosilva's control panel | |
41 | 41 | And I follow "Manage Content" |
42 | 42 | And I follow "New content" |
43 | 43 | And I follow "Blog" |
44 | 44 | And I fill in "Title" with "Blog One" |
45 | 45 | And I press "Save" |
46 | - Then I go to the Control panel | |
46 | + Then I go to joaosilva's control panel | |
47 | 47 | And I follow "Manage Content" |
48 | 48 | And I follow "New content" |
49 | 49 | And I follow "Blog" |
... | ... | @@ -53,7 +53,7 @@ Feature: blog |
53 | 53 | And I should be on /joaosilva/blog-two |
54 | 54 | |
55 | 55 | Scenario: cancel button back to cms |
56 | - Given I go to the Control panel | |
56 | + Given I go to joaosilva's control panel | |
57 | 57 | And I follow "Manage Content" |
58 | 58 | And I follow "New content" |
59 | 59 | And I follow "Blog" |
... | ... | @@ -61,7 +61,7 @@ Feature: blog |
61 | 61 | Then I should be on /myprofile/joaosilva/cms |
62 | 62 | |
63 | 63 | Scenario: cancel button back to myprofile |
64 | - Given I go to the Control panel | |
64 | + Given I go to joaosilva's control panel | |
65 | 65 | And I follow "Create blog" |
66 | 66 | When I follow "Cancel" within ".main-block" |
67 | 67 | Then I should be on /myprofile/joaosilva |
... | ... | @@ -71,7 +71,7 @@ Feature: blog |
71 | 71 | | owner | name | |
72 | 72 | | joaosilva | Blog One | |
73 | 73 | | joaosilva | Blog Two | |
74 | - And I go to the Control panel | |
74 | + And I go to joaosilva's control panel | |
75 | 75 | When I follow "Configure blog" |
76 | 76 | Then I should be on /myprofile/joaosilva/cms |
77 | 77 | |
... | ... | @@ -79,7 +79,7 @@ Feature: blog |
79 | 79 | Given the following blogs |
80 | 80 | | owner | name | |
81 | 81 | | joaosilva | Blog One | |
82 | - And I go to the Control panel | |
82 | + And I go to joaosilva's control panel | |
83 | 83 | When I follow "Configure blog" |
84 | 84 | Then I should be on edit "Blog One" by joaosilva |
85 | 85 | |
... | ... | @@ -89,14 +89,14 @@ Feature: blog |
89 | 89 | | owner | name | |
90 | 90 | | joaosilva | Blog One | |
91 | 91 | And I go to /joaosilva/blog-one |
92 | - When I follow "Configure blog" and wait | |
92 | + When I follow "Configure blog" | |
93 | 93 | Then I should be on edit "Blog One" by joaosilva |
94 | 94 | |
95 | 95 | Scenario: change address of blog |
96 | 96 | Given the following blogs |
97 | 97 | | owner | name | |
98 | 98 | | joaosilva | Blog One | |
99 | - And I go to the Control panel | |
99 | + And I go to joaosilva's control panel | |
100 | 100 | And I follow "Configure blog" |
101 | 101 | And I fill in "Address" with "blog-two" |
102 | 102 | And I press "Save" |
... | ... | @@ -104,7 +104,7 @@ Feature: blog |
104 | 104 | Then I should see "Blog One" |
105 | 105 | |
106 | 106 | Scenario: display tag list field when creating new blog |
107 | - Given I go to the Control panel | |
107 | + Given I go to joaosilva's control panel | |
108 | 108 | And I follow "Manage Content" |
109 | 109 | And I follow "New content" |
110 | 110 | When I follow "Blog" | ... | ... |
features/browse.feature
... | ... | @@ -17,32 +17,34 @@ Feature: browse |
17 | 17 | |
18 | 18 | @selenium |
19 | 19 | Scenario: Show people browse menu |
20 | - Given I should not see "More Recent" | |
21 | - And I should not see "More Active" | |
22 | - And I should not see "More Popular" | |
23 | - When I click "#submenu-people-trigger" | |
24 | - Then I should see "More Recent" | |
25 | - And I should see "More Active" | |
26 | - And I should see "More Popular" | |
20 | + Given I should not see "More recent" | |
21 | + And I should not see "More active" | |
22 | + And I should not see "More popular" | |
23 | + And display "#submenu-people-trigger" | |
24 | + When I follow "submenu-people-trigger" | |
25 | + Then I should see "More recent" | |
26 | + And I should see "More active" | |
27 | + And I should see "More popular" | |
27 | 28 | |
28 | 29 | @selenium |
29 | 30 | Scenario: People browse menu should add logged information |
30 | 31 | Given I am logged in as "joaosilva" |
31 | - And I should not see "More Recent" | |
32 | - And I should not see "More Active" | |
33 | - And I should not see "More Popular" | |
32 | + And I should not see "More recent" | |
33 | + And I should not see "More active" | |
34 | + And I should not see "More popular" | |
34 | 35 | And I should not see "Invite friends" |
35 | 36 | And I should not see "My friends" |
36 | - When I click "#submenu-people-trigger" | |
37 | - Then I should see "More Recent" | |
38 | - And I should see "More Active" | |
39 | - And I should see "More Popular" | |
37 | + And display "#submenu-people-trigger" | |
38 | + When I follow "submenu-people-trigger" | |
39 | + Then I should see "More recent" | |
40 | + And I should see "More active" | |
41 | + And I should see "More popular" | |
40 | 42 | And I should see "Invite friends" |
41 | 43 | And I should see "My friends" |
42 | 44 | |
43 | 45 | Scenario: Browse people by query |
44 | 46 | Given I go to /search/people |
45 | - When I fill in "Silva" for "query" | |
47 | + When I fill in "Silva" for "search-input" | |
46 | 48 | And I press "Search" |
47 | 49 | Then I should see "Joao Silva" |
48 | 50 | And I should see "Pedro Silva" |
... | ... | @@ -54,31 +56,33 @@ Feature: browse |
54 | 56 | Scenario: Communities browse menu should add logged information |
55 | 57 | Given I am logged in as "joaosilva" |
56 | 58 | When I go to /joaosilva |
57 | - Then I should not see "More Recent" | |
58 | - And I should not see "More Active" | |
59 | - And I should not see "More Popular" | |
59 | + Then I should not see "More recent" | |
60 | + And I should not see "More active" | |
61 | + And I should not see "More popular" | |
60 | 62 | And I should not see "My communities" |
61 | 63 | And I should not see "New community" |
62 | - When I click "#submenu-communities-trigger" | |
63 | - Then I should see "More Recent" | |
64 | - And I should see "More Active" | |
65 | - And I should see "More Popular" | |
64 | + And display "#submenu-communities-trigger" | |
65 | + When I follow "submenu-communities-trigger" | |
66 | + Then I should see "More recent" | |
67 | + And I should see "More active" | |
68 | + And I should see "More popular" | |
66 | 69 | And I should see "My communities" |
67 | 70 | And I should see "New community" |
68 | 71 | |
69 | 72 | @selenium |
70 | 73 | Scenario: Show communities browse menu |
71 | - Given I should not see "More Recent" | |
72 | - And I should not see "More Active" | |
73 | - And I should not see "More Popular" | |
74 | - When I click "#submenu-communities-trigger" | |
75 | - Then I should see "More Recent" | |
76 | - And I should see "More Active" | |
77 | - And I should see "More Popular" | |
74 | + Given I should not see "More recent" | |
75 | + And I should not see "More active" | |
76 | + And I should not see "More popular" | |
77 | + And display "#submenu-communities-trigger" | |
78 | + When I follow "submenu-communities-trigger" | |
79 | + Then I should see "More recent" | |
80 | + And I should see "More active" | |
81 | + And I should see "More popular" | |
78 | 82 | |
79 | 83 | Scenario: Browse communities by query |
80 | 84 | When I go to /search/communities |
81 | - And I fill in "Neto" for "query" | |
85 | + And I fill in "Neto" for "search-input" | |
82 | 86 | And I press "Search" |
83 | 87 | Then I should see "Community Neto" |
84 | 88 | And I should not see "Joao Silva" |
... | ... | @@ -88,13 +92,14 @@ Feature: browse |
88 | 92 | |
89 | 93 | @selenium |
90 | 94 | Scenario: Show contents browse menu |
91 | - Given I should not see "More Comments" | |
92 | - And I should not see "More Views" | |
93 | - And I should not see "More Recent" | |
94 | - When I click "#submenu-contents-trigger" | |
95 | - Then I should see "More Comments" | |
96 | - And I should see "More Views" | |
97 | - And I should see "More Recent" | |
95 | + Given I should not see "Most commented" | |
96 | + And I should not see "More viewed" | |
97 | + And I should not see "More recent" | |
98 | + And display "#submenu-contents-trigger" | |
99 | + When I follow "submenu-contents-trigger" | |
100 | + Then I should see "Most commented" | |
101 | + And I should see "More viewed" | |
102 | + And I should see "More recent" | |
98 | 103 | |
99 | 104 | Scenario: Browse contents by query |
100 | 105 | Given the following articles |
... | ... | @@ -103,7 +108,7 @@ Feature: browse |
103 | 108 | | joaosilva | Bees and ants are insects | this is another article | |
104 | 109 | | joaosilva | Ants are small | this is another article | |
105 | 110 | When I go to /search/contents |
106 | - And I fill in "bees" for "query" | |
111 | + And I fill in "bees" for "search-input" | |
107 | 112 | And I press "Search" |
108 | 113 | Then I should see "Bees can fly" |
109 | 114 | And I should see "Bees and ants are insects" | ... | ... |
features/browse_catalogs.feature
... | ... | @@ -18,7 +18,7 @@ Feature: browse catalogs |
18 | 18 | |
19 | 19 | Scenario: display titles |
20 | 20 | Then I should see "Associação de Artesanato de Bonito" |
21 | - And I should see "Products/Services" within "#product-list" | |
21 | + And I should see "Products/Services" | |
22 | 22 | |
23 | 23 | Scenario: display the simplest possible product |
24 | 24 | Given the following products |
... | ... | @@ -132,7 +132,7 @@ Feature: browse catalogs |
132 | 132 | And I should not see "qualifiers" |
133 | 133 | And I should not see "price composition" |
134 | 134 | |
135 | - @selenium | |
135 | + @selenium-fixme | |
136 | 136 | Scenario: display description button when needed (but not the description) |
137 | 137 | Given the following products |
138 | 138 | | owner | category | name | price | description | |
... | ... | @@ -142,22 +142,22 @@ Feature: browse catalogs |
142 | 142 | Then I should see "Produto2" within "li.product-link" |
143 | 143 | And I should see "12.34" within "span.product-price" |
144 | 144 | And I should see "description" within "#product-description-button" |
145 | - And the "product-description-button" should be visible | |
145 | + And "description" should not be visible within "product-description-button" | |
146 | 146 | And I should see "A small description" within "#product-description" |
147 | - And the "product-description" should not be visible | |
147 | + And "A small description for a product that doesn't exist" should not be visible within "product-description" | |
148 | 148 | |
149 | - @selenium | |
149 | + @selenium-fixme | |
150 | 150 | Scenario: display description when button is clicked |
151 | 151 | Given the following products |
152 | 152 | | owner | category | name | price | description | |
153 | 153 | | artebonito | categ1 | Produto3 | 12.34 | A small description for a product that doesn't exist. | |
154 | 154 | And I am on /catalog/artebonito |
155 | 155 | And I reload and wait for the page |
156 | - When I click "product-description-button" | |
156 | + When I follow "product-description-button" | |
157 | 157 | Then I should see "A small description" within "#product-description" |
158 | - And the "product-description" should be visible | |
158 | + And "A small description for a product that doesn't exist" should not be visible within "product-description" | |
159 | 159 | |
160 | - @selenium | |
160 | + @selenium-fixme | |
161 | 161 | Scenario: hide description |
162 | 162 | Given the following products |
163 | 163 | | owner | category | name | price | description | |
... | ... | @@ -198,7 +198,7 @@ Feature: browse catalogs |
198 | 198 | And I should see "Organic" within "span.search-product-qualifier" |
199 | 199 | And I should not see "price composition" |
200 | 200 | |
201 | - @selenium | |
201 | + @selenium-fixme | |
202 | 202 | Scenario: not display price composition button if price is not described |
203 | 203 | Given the following product |
204 | 204 | | owner | category | name | price | |
... | ... | @@ -212,7 +212,7 @@ Feature: browse catalogs |
212 | 212 | And I should see "10.00" within "span.product-price" |
213 | 213 | And the "#product-price-composition-button" should not be visible |
214 | 214 | |
215 | - @selenium | |
215 | + @selenium-fixme | |
216 | 216 | Scenario: display price composition button (but not inputs) |
217 | 217 | Given the following product |
218 | 218 | | owner | category | name | price | |
... | ... | @@ -229,7 +229,7 @@ Feature: browse catalogs |
229 | 229 | And I should see "food" within "#product-price-composition" |
230 | 230 | And I should see "10.00" within "#product-price-composition" |
231 | 231 | |
232 | - @selenium | |
232 | + @selenium-fixme | |
233 | 233 | Scenario: display price composition when button is clicked |
234 | 234 | Given the following product |
235 | 235 | | owner | category | name | price | |
... | ... | @@ -244,7 +244,7 @@ Feature: browse catalogs |
244 | 244 | And I should see "food" within "#product-price-composition" |
245 | 245 | And I should see "10.88" within "#product-price-composition" |
246 | 246 | |
247 | - @selenium | |
247 | + @selenium-fixme | |
248 | 248 | Scenario: display inputs and raw materials button when not completely filled |
249 | 249 | Given the following product |
250 | 250 | | owner | category | name | price | |
... | ... | @@ -260,7 +260,7 @@ Feature: browse catalogs |
260 | 260 | Then the "#inputs-button" should be visible |
261 | 261 | And I should see "inputs and raw materials" within "#inputs-button" |
262 | 262 | |
263 | - @selenium | |
263 | + @selenium-fixme | |
264 | 264 | Scenario: display inputs and raw materials button |
265 | 265 | Given the following product |
266 | 266 | | owner | category | name | price | |
... | ... | @@ -280,7 +280,7 @@ Feature: browse catalogs |
280 | 280 | And the "#inputs-description" should not be visible |
281 | 281 | And I should see "7.0 Liter of food" within "#inputs-description" |
282 | 282 | |
283 | - @selenium | |
283 | + @selenium-fixme | |
284 | 284 | Scenario: display inputs and raw materials description |
285 | 285 | Given the following product |
286 | 286 | | owner | category | name | price | |
... | ... | @@ -297,7 +297,7 @@ Feature: browse catalogs |
297 | 297 | Then the "#inputs-description" should be visible |
298 | 298 | And I should see "7.0 Liter of food" within "#inputs-description" |
299 | 299 | |
300 | - @selenium | |
300 | + @selenium-fixme | |
301 | 301 | Scenario: hide inputs and raw materials |
302 | 302 | Given the following product |
303 | 303 | | owner | category | name | price | | ... | ... |
features/browse_enterprises.feature
... | ... | @@ -24,7 +24,7 @@ Scenario: show profile links button |
24 | 24 | And I should not see "Members" |
25 | 25 | And I should not see "Agenda" |
26 | 26 | |
27 | -@selenium | |
27 | +@selenium-fixme | |
28 | 28 | Scenario: show profile links when clicked |
29 | 29 | Given I am on /assets/enterprises |
30 | 30 | When I follow "Profile links" |
... | ... | @@ -32,7 +32,7 @@ Scenario: show profile links when clicked |
32 | 32 | And I should see "Members" within "ul.menu-submenu-list" |
33 | 33 | And I should see "Agenda" within "ul.menu-submenu-list" |
34 | 34 | |
35 | -@selenium | |
35 | +@selenium-fixme | |
36 | 36 | Scenario: go to catalog when click on products link |
37 | 37 | Given I am on /assets/enterprises |
38 | 38 | When I follow "Profile links" | ... | ... |
features/categories_block.feature
... | ... | @@ -25,7 +25,7 @@ Feature: categories_block |
25 | 25 | | environment | CategoriesBlock | |
26 | 26 | And I am logged in as admin |
27 | 27 | |
28 | - @selenium | |
28 | + @selenium @ignore-hidden-elements | |
29 | 29 | Scenario: List just product categories |
30 | 30 | Given I go to /admin/environment_design |
31 | 31 | And I follow "Edit" within ".categories-block" |
... | ... | @@ -33,11 +33,11 @@ Feature: categories_block |
33 | 33 | When I press "Save" |
34 | 34 | Then I should see "Food" |
35 | 35 | And I should see "Book" |
36 | - And I should not see "Vegetarian" | |
37 | - And I should not see "Steak" | |
38 | - And I should not see "Fiction" | |
36 | + And "Vegetarian" should not be visible within "span#category-name" | |
37 | + And "Steak" should not be visible within "span#category-name" | |
38 | + And "Fiction" should not be visible within "span#category-name" | |
39 | 39 | |
40 | - @selenium | |
40 | + @selenium @ignore-hidden-elements | |
41 | 41 | Scenario: Show submenu if it exists |
42 | 42 | Given I go to /admin/environment_design |
43 | 43 | And I follow "Edit" within ".categories-block" |
... | ... | @@ -45,40 +45,39 @@ Feature: categories_block |
45 | 45 | And I press "Save" |
46 | 46 | Then I should see "Food" |
47 | 47 | And I should see "Book" |
48 | - And I should not see "Vegetarian" | |
49 | - And I should not see "Steak" | |
50 | - And I should not see "Literature" | |
51 | - When I click ".category-link-expand category-root" | |
48 | + And "Vegetarian" should not be visible within "span#category-name" | |
49 | + And "Steak" should not be visible within "span#category-name" | |
50 | + And "Literature" should not be visible within "span#category-name" | |
51 | + When I follow "block_2_category_2" | |
52 | 52 | Then I should see "Literature" |
53 | - When I click ".category-link-expand category-root" | |
53 | + When I follow "block_2_category_1" | |
54 | 54 | Then I should see "Vegetarian" |
55 | 55 | And I should see "Steak" |
56 | 56 | And I should not see "Fiction" |
57 | 57 | |
58 | - @selenium | |
58 | + @selenium @ignore-hidden-elements | |
59 | 59 | Scenario: Show only one submenu per time |
60 | 60 | Given I go to /admin/environment_design |
61 | 61 | And I follow "Edit" within ".categories-block" |
62 | 62 | And I check "Product" |
63 | 63 | And I press "Save" |
64 | 64 | Then I should see "Book" |
65 | - And I should not see "Literature" | |
66 | - When I click ".category-link-expand category-root" | |
65 | + And "Literature" should not be visible within "span#category-name" | |
66 | + When I follow "block_2_category_2" | |
67 | 67 | Then I should see "Literature" |
68 | 68 | |
69 | - @selenium | |
69 | + @selenium @ignore-hidden-elements | |
70 | 70 | Scenario: List just general categories |
71 | 71 | Given I go to /admin/environment_design |
72 | 72 | And I follow "Edit" within ".categories-block" |
73 | - And I check "Generic Category" | |
73 | + And I check "Generic category" | |
74 | 74 | When I press "Save" |
75 | 75 | Then I should see "Wood" |
76 | 76 | |
77 | - @selenium | |
77 | + @selenium @ignore-hidden-elements | |
78 | 78 | Scenario: List just regions |
79 | 79 | Given I go to /admin/environment_design |
80 | 80 | And I follow "Edit" within ".categories-block" |
81 | 81 | And I check "Region" |
82 | 82 | When I press "Save" |
83 | 83 | Then I should see "Bahia" |
84 | - | ... | ... |
features/change_organization_name.feature
... | ... | @@ -12,12 +12,12 @@ Feature: change organization name |
12 | 12 | | joaosilva | Joao Silva | |
13 | 13 | And "Joao Silva" is admin of "Sample Community" |
14 | 14 | And I am logged in as "joaosilva" |
15 | - And I am on Sample Community's control panel | |
15 | + And I am on sample-community's control panel | |
16 | 16 | And I follow "Community Info and settings" |
17 | 17 | And I fill in "Name" with "New Sample Community" |
18 | 18 | When I press "Save" |
19 | - Then I should be on New Sample Community's control panel | |
20 | - | |
19 | + Then I should be on sample-community's control panel | |
20 | + And I should see "New Sample Community" within "title" | |
21 | 21 | |
22 | 22 | Scenario: changing enterprise's name |
23 | 23 | Given the following enterprises |
... | ... | @@ -28,8 +28,9 @@ Feature: change organization name |
28 | 28 | | joaosilva | Joao Silva | |
29 | 29 | And "Joao Silva" is admin of "Sample Enterprise" |
30 | 30 | And I am logged in as "joaosilva" |
31 | - And I am on Sample Enterprise's control panel | |
31 | + And I am on sample-enterprise's control panel | |
32 | 32 | And I follow "Enterprise Info and settings" |
33 | 33 | And I fill in "Name" with "New Sample Enterprise" |
34 | 34 | When I press "Save" |
35 | - Then I should be on New Sample Enterprise's control panel | |
35 | + Then I should be on sample-enterprise's control panel | |
36 | + And I should see "New Sample Enterprise" within "title" | ... | ... |
features/chat.feature
... | ... | @@ -17,7 +17,7 @@ Feature: chat |
17 | 17 | Scenario: provide link to open chat |
18 | 18 | Given feature "xmpp_chat" is enabled on environment |
19 | 19 | And I am logged in as "tame" |
20 | - Then I should see "Open chat" link | |
20 | + Then I should see "Open chat" within "#user" | |
21 | 21 | |
22 | 22 | @selenium |
23 | 23 | Scenario: provide the chat online users content |
... | ... | @@ -30,18 +30,18 @@ Feature: chat |
30 | 30 | Given the profile "tame" has no blocks |
31 | 31 | And feature "xmpp_chat" is enabled on environment |
32 | 32 | And I am logged in as "tame" |
33 | - And I go to Tame's profile | |
34 | - When I click "#chat-online-users-title" | |
33 | + And I go to tame's profile | |
34 | + When I follow "chat-online-users-title" | |
35 | 35 | Then I should see "Maria Silva" |
36 | 36 | And I should see "Jose Silva" |
37 | 37 | |
38 | 38 | Scenario: not provide link to chat when environment not support that |
39 | 39 | Given I am logged in as "tame" |
40 | - Then I should not see "Open chat" link | |
40 | + Then I should not see "Open chat" within "#user" | |
41 | 41 | |
42 | 42 | Scenario: not provide link to chat when the user is logged out |
43 | - Given I am on Tame's homepage | |
44 | - Then I should not see "Open chat" link | |
43 | + Given I am on tame's homepage | |
44 | + Then I should not see "Open chat" within "#user" | |
45 | 45 | |
46 | 46 | @selenium |
47 | 47 | Scenario: not provide the chat online users list when environment not support that |
... | ... | @@ -71,8 +71,8 @@ Feature: chat |
71 | 71 | Given the profile "tame" has no blocks |
72 | 72 | And feature "xmpp_chat" is enabled on environment |
73 | 73 | And I am logged in as "tame" |
74 | - And I go to Tame's profile | |
75 | - When I click "#chat-online-users-title" | |
74 | + And I go to tame's profile | |
75 | + When I follow "chat-online-users-title" | |
76 | 76 | And I follow "Maria Silva" |
77 | 77 | And I select window "noosfero_chat" |
78 | 78 | Then I should see "Chat - Colivre.net - Friends online (0)" |
... | ... | @@ -83,7 +83,7 @@ Feature: chat |
83 | 83 | And I am logged in as "tame" |
84 | 84 | When I follow "Open chat" |
85 | 85 | And I select window "noosfero_chat" |
86 | - Then I should see "Offline" link | |
86 | + Then I should see "Offline" within "a" | |
87 | 87 | |
88 | 88 | @selenium |
89 | 89 | Scenario: view options to change my chat status through menu |
... | ... | @@ -91,13 +91,13 @@ Feature: chat |
91 | 91 | And I am logged in as "tame" |
92 | 92 | And I follow "Open chat" |
93 | 93 | When I select window "noosfero_chat" |
94 | - Then the "#chat-online" should not be visible | |
95 | - And the "#chat-busy" should not be visible | |
96 | - And the "#chat-disconnect" should not be visible | |
94 | + Then "Online" should not be visible within "#user-status" | |
95 | + And "Busy" should not be visible within "#user-status" | |
96 | + And "Sign out of chat" should not be visible within "#user-status" | |
97 | 97 | When I follow "Offline" |
98 | - Then the "#chat-connect" should be visible | |
99 | - And the "#chat-busy" should be visible | |
100 | - And the "#chat-disconnect" should be visible | |
98 | + Then "Online" should be visible within "#user-status" | |
99 | + And "Busy" should be visible within "#user-status" | |
100 | + And "Sign out of chat" should be visible within "#user-status" | |
101 | 101 | |
102 | 102 | @selenium |
103 | 103 | Scenario: link to open chatroom of a community |
... | ... | @@ -107,8 +107,8 @@ Feature: chat |
107 | 107 | And "Tame" is a member of "Autoramas" |
108 | 108 | And feature "xmpp_chat" is enabled on environment |
109 | 109 | And I am logged in as "tame" |
110 | - When I go to Autoramas's profile | |
111 | - Then I should see "Enter chat room" link | |
110 | + When I go to autoramas's profile | |
111 | + Then I should see "Enter chat room" | |
112 | 112 | |
113 | 113 | @selenium |
114 | 114 | Scenario: not see link to open chatroom of a community if not a member |
... | ... | @@ -117,8 +117,8 @@ Feature: chat |
117 | 117 | | autoramas | Autoramas | |
118 | 118 | And feature "xmpp_chat" is enabled on environment |
119 | 119 | And I am logged in as "tame" |
120 | - When I go to Autoramas's profile | |
121 | - Then I should not see "Enter chat room" link | |
120 | + When I go to autoramas's profile | |
121 | + Then I should not see "Enter chat room" within "a" | |
122 | 122 | |
123 | 123 | @selenium |
124 | 124 | Scenario: not see link to open chatroom of a community if xmpp_chat disabled |
... | ... | @@ -127,8 +127,8 @@ Feature: chat |
127 | 127 | | autoramas | Autoramas | |
128 | 128 | And "Tame" is a member of "Autoramas" |
129 | 129 | And I am logged in as "tame" |
130 | - When I go to Autoramas's profile | |
131 | - Then I should not see "Enter chat room" link | |
130 | + When I go to autoramas's profile | |
131 | + Then I should not see "Enter chat room" within "a" | |
132 | 132 | |
133 | 133 | @selenium |
134 | 134 | Scenario: open chatroom of a community in a new window |
... | ... | @@ -138,7 +138,7 @@ Feature: chat |
138 | 138 | | autoramas | Autoramas | |
139 | 139 | And "Tame" is a member of "Autoramas" |
140 | 140 | And I am logged in as "tame" |
141 | - When I go to Autoramas's profile | |
141 | + When I go to autoramas's profile | |
142 | 142 | And I follow "Enter chat room" |
143 | 143 | And I select window "noosfero_chat" |
144 | 144 | Then I should see "Chat - Colivre.net - Friends online (0)" | ... | ... |
features/clickable_images.feature
... | ... | @@ -22,7 +22,7 @@ Feature: clickable images |
22 | 22 | | owner | name | image | dimensions | |
23 | 23 | | booking | real | rails.png | 50x64 | |
24 | 24 | When I go to /booking/real |
25 | - Then I should not see "Zoom in" | |
25 | + Then "Zoom in" should not be visible within "a#zoomify-image" | |
26 | 26 | |
27 | 27 | @selenium |
28 | 28 | Scenario: not show link if image does not have dimensions set |
... | ... | @@ -30,9 +30,9 @@ Feature: clickable images |
30 | 30 | | owner | name | image | |
31 | 31 | | booking | not set | rails.png | |
32 | 32 | When I go to /booking/not-set |
33 | - Then I should not see "Zoom in" | |
33 | + Then "Zoom in" should not be visible within "a#zoomify-image" | |
34 | 34 | |
35 | - @selenium | |
35 | + @selenium-fixme | |
36 | 36 | Scenario: copy style from image |
37 | 37 | Given the following article with image |
38 | 38 | | owner | name | image | style | dimensions | |
... | ... | @@ -40,11 +40,11 @@ Feature: clickable images |
40 | 40 | When I go to /booking/with-style |
41 | 41 | Then "zoomable-image" should be right aligned |
42 | 42 | |
43 | - @selenium | |
43 | + @selenium-fixme | |
44 | 44 | Scenario: zoom image |
45 | 45 | Given the following article with image |
46 | 46 | | owner | name | image | dimensions | |
47 | 47 | | booking | zoom | rails.png | 25x32 | |
48 | 48 | When I go to /booking/zoom |
49 | - And I follow "Zoom in" | |
50 | - Then the "#fancybox-wrap" should be visible | |
49 | + And I follow "Zoom in" within "a#zoomify-image" | |
50 | + Then I should see "fancybox-wrap" | ... | ... |
features/comment.feature
... | ... | @@ -14,19 +14,23 @@ Feature: comment |
14 | 14 | | article | author | title | body | |
15 | 15 | | article with comment | booking | hi | how are you? | |
16 | 16 | | article with comment | booking | hello | i am fine | |
17 | + And feature "captcha_for_logged_users" is disabled on environment | |
18 | + And I am logged in as "booking" | |
17 | 19 | |
18 | 20 | Scenario: not post a comment without javascript |
19 | 21 | Given I am on /booking/article-to-comment |
20 | - And I fill in "Name" with "Joey Ramone" | |
21 | - And I fill in "e-mail" with "joey@ramones.com" | |
22 | + And I follow "Post a comment" | |
22 | 23 | And I fill in "Title" with "Hey ho, let's go!" |
23 | 24 | And I fill in "Enter your comment" with "Hey ho, let's go!" |
24 | 25 | When I press "Post comment" |
25 | 26 | Then I should not see "Hey ho, let's go" |
26 | 27 | |
27 | - @selenium | |
28 | + # This test requires some way to overcome the captcha with unauthenticated | |
29 | + # user. | |
30 | + @selenium-fixme | |
28 | 31 | Scenario: post a comment while not authenticated |
29 | 32 | Given I am on /booking/article-to-comment |
33 | + And I follow "Post a comment" | |
30 | 34 | And I fill in "Name" with "Joey Ramone" |
31 | 35 | And I fill in "e-mail" with "joey@ramones.com" |
32 | 36 | And I fill in "Title" with "Hey ho, let's go!" |
... | ... | @@ -36,8 +40,8 @@ Feature: comment |
36 | 40 | |
37 | 41 | @selenium |
38 | 42 | Scenario: post comment while authenticated |
39 | - Given I am logged in as "booking" | |
40 | - And I am on /booking/article-to-comment | |
43 | + Given I am on /booking/article-to-comment | |
44 | + And I follow "Post a comment" | |
41 | 45 | And I fill in "Title" with "Hey ho, let's go!" |
42 | 46 | And I fill in "Enter your comment" with "Hey ho, let's go!" |
43 | 47 | When I press "Post comment" |
... | ... | @@ -48,8 +52,8 @@ Feature: comment |
48 | 52 | Given the following files |
49 | 53 | | owner | file | mime | |
50 | 54 | | booking | rails.png | image/png | |
51 | - Given I am logged in as "booking" | |
52 | 55 | And I am on /booking/rails.png?view=true |
56 | + And I follow "Post a comment" | |
53 | 57 | And I fill in "Title" with "Hey ho, let's go!" |
54 | 58 | And I fill in "Enter your comment" with "Hey ho, let's go!" |
55 | 59 | When I press "Post comment" |
... | ... | @@ -57,35 +61,34 @@ Feature: comment |
57 | 61 | |
58 | 62 | @selenium |
59 | 63 | Scenario: show error messages when make a blank comment |
60 | - Given I am logged in as "booking" | |
61 | - And I am on /booking/article-to-comment | |
64 | + Given I am on /booking/article-to-comment | |
65 | + And I follow "Post a comment" | |
62 | 66 | When I press "Post comment" |
63 | - Then I should see "Title can't be blank" | |
64 | - And I should see "Body can't be blank" | |
67 | + Then I should see "Body can't be blank" | |
65 | 68 | |
66 | - @selenium | |
69 | + @selenium-fixme | |
67 | 70 | Scenario: disable post comment button |
68 | 71 | Given I am on /booking/article-to-comment |
69 | - And I fill in "Name" with "Joey Ramone" | |
70 | - And I fill in "e-mail" with "joey@ramones.com" | |
72 | + And I follow "Post a comment" | |
71 | 73 | And I fill in "Title" with "Hey ho, let's go!" |
72 | 74 | And I fill in "Enter your comment" with "Hey ho, let's go!" |
73 | 75 | When I press "Post comment" |
74 | - Then the "value.Post comment" button should not be enabled | |
75 | - And I should see "Hey ho, let's go" | |
76 | +# Implement these steps... | |
77 | +# Then "Post comment" button should not be enabled | |
78 | +# And I should see "Hey ho, let's go" | |
76 | 79 | |
77 | 80 | @selenium |
78 | 81 | Scenario: render comment form and go to bottom |
79 | 82 | Given I am on /booking/article-with-comment |
80 | - When I follow "Post a comment" within ".post-comment-button" | |
81 | - Then I should see "Enter your comment" within "div#page-comment-form div.post_comment_box.opened" | |
82 | - And I should be exactly on /booking/article-with-comment | |
83 | - And I should be moved to anchor "comment_form" | |
83 | + When I follow "Post a comment" | |
84 | + Then I should see "Enter your comment" | |
85 | + And I should be on /booking/article-with-comment | |
84 | 86 | |
85 | 87 | @selenium |
86 | 88 | Scenario: keep comments field filled while trying to do a comment |
87 | 89 | Given I am on /booking/article-with-comment |
88 | - And I fill in "Name" with "Joey Ramone" | |
90 | + And I follow "Post a comment" | |
91 | + And I fill in "Title" with "Joey Ramone" | |
89 | 92 | When I press "Post comment" |
90 | - Then the "Name" field should contain "Joey Ramone" | |
91 | - And I should see "errors prohibited" | |
93 | + Then the "Title" field should contain "Joey Ramone" | |
94 | + And I should see "Body can't be blank" | ... | ... |
features/comment_reply.feature
... | ... | @@ -25,7 +25,7 @@ Feature: comment |
25 | 25 | Then I should not see "Enter your comment" within "div.comment-balloon" |
26 | 26 | And I should see "Reply" within "div.comment-balloon" |
27 | 27 | |
28 | - @selenium | |
28 | + @selenium-fixme | |
29 | 29 | Scenario: show error messages when make a blank comment reply |
30 | 30 | Given I am logged in as "booking" |
31 | 31 | And I go to /booking/article-to-comment |
... | ... | @@ -51,9 +51,9 @@ Feature: comment |
51 | 51 | Given I am on /booking/article-to-comment |
52 | 52 | When I follow "Reply" within ".comment-balloon" |
53 | 53 | And I follow "Cancel" within ".comment-balloon" |
54 | - Then I should see "Enter your comment" within "div.comment_reply.closed" | |
54 | + Then I should not see "Enter your comment" within "div.comment_reply.closed" | |
55 | 55 | |
56 | - @selenium | |
56 | + @selenium-fixme | |
57 | 57 | Scenario: not render same reply form twice |
58 | 58 | Given I am on /booking/article-to-comment |
59 | 59 | When I follow "Reply" within ".comment-balloon" |
... | ... | @@ -62,7 +62,7 @@ Feature: comment |
62 | 62 | Then there should be 1 "comment_form" within "comment_reply" |
63 | 63 | And I should see "Enter your comment" within "div.comment_reply.opened" |
64 | 64 | |
65 | - @selenium | |
65 | + @selenium-fixme | |
66 | 66 | Scenario: reply a comment |
67 | 67 | Given I go to /booking/another-article |
68 | 68 | And I follow "Reply" within ".comment-balloon" |
... | ... | @@ -74,7 +74,7 @@ Feature: comment |
74 | 74 | Then I should see "Hey ho, let's go" within "ul.comment-replies" |
75 | 75 | And there should be 1 "comment-replies" within "article-comment" |
76 | 76 | |
77 | - @selenium | |
77 | + @selenium-fixme | |
78 | 78 | Scenario: redirect to right place after reply a picture comment |
79 | 79 | Given the following files |
80 | 80 | | owner | file | mime | | ... | ... |
features/contact.feature
... | ... | @@ -14,8 +14,8 @@ In order to ask questions and solve problems |
14 | 14 | |
15 | 15 | @selenium |
16 | 16 | Scenario: without states |
17 | - Given I am on Sample Community's homepage | |
18 | - When I follow "Send an e-mail" and wait | |
17 | + Given I am on sample-community's homepage | |
18 | + When I follow "Send an e-mail" | |
19 | 19 | Then I should not see "City and state" |
20 | 20 | |
21 | 21 | @selenium |
... | ... | @@ -23,7 +23,6 @@ In order to ask questions and solve problems |
23 | 23 | Given the following states |
24 | 24 | | name | |
25 | 25 | | Bahia | |
26 | - And I am on Sample Community's homepage | |
27 | - When I follow "Send an e-mail" and wait | |
26 | + And I am on sample-community's homepage | |
27 | + When I follow "Send an e-mail" | |
28 | 28 | Then I should see "City and state" |
29 | - | ... | ... |
features/create_community.feature
... | ... | @@ -11,7 +11,7 @@ Feature: create community |
11 | 11 | Scenario: a user creates a community |
12 | 12 | Given I am logged in as "joaosilva" |
13 | 13 | And feature "admin_must_approve_new_communities" is disabled on environment |
14 | - And I go to the Control panel | |
14 | + And I go to joaosilva's control panel | |
15 | 15 | And I follow "Manage my groups" |
16 | 16 | When I follow "Create a new community" |
17 | 17 | And I fill in "Name" with "Fancy community" |
... | ... | @@ -22,7 +22,7 @@ Feature: create community |
22 | 22 | Scenario: a user creates a community when environment moderates it |
23 | 23 | Given I am logged in as "joaosilva" |
24 | 24 | And feature "admin_must_approve_new_communities" is enabled on environment |
25 | - When I go to the Control panel | |
25 | + And I go to joaosilva's control panel | |
26 | 26 | And I follow "Manage my groups" |
27 | 27 | And I follow "Create a new community" |
28 | 28 | And I fill in "Name" with "Community for moderation" |
... | ... | @@ -32,7 +32,7 @@ Feature: create community |
32 | 32 | Scenario: a user tries to create a community without a name |
33 | 33 | Given I am logged in as "joaosilva" |
34 | 34 | And feature "admin_must_approve_new_communities" is disabled on environment |
35 | - And I go to the Control panel | |
35 | + And I go to joaosilva's control panel | |
36 | 36 | And I follow "Manage my groups" |
37 | 37 | When I follow "Create a new community" |
38 | 38 | And I press "Create" |
... | ... | @@ -42,20 +42,20 @@ Feature: create community |
42 | 42 | Given I am logged in as admin |
43 | 43 | And feature "admin_must_approve_new_communities" is enabled on environment |
44 | 44 | When I create community "Community for approval" |
45 | - And I go to the Control panel | |
45 | + And I go to admin_user's control panel | |
46 | 46 | Then I should see "admin_user wants to create community Community for approval" |
47 | 47 | |
48 | 48 | Scenario: environment admin accepts new community task |
49 | 49 | Given I am logged in as admin |
50 | 50 | And feature "admin_must_approve_new_communities" is enabled on environment |
51 | 51 | When I create community "Community for approval" |
52 | - And I go to the Control panel | |
52 | + And I go to admin_user's control panel | |
53 | 53 | And I follow "Process requests" |
54 | 54 | And I should see "admin_user wants to create community Community for approval" |
55 | 55 | And I choose "Accept" |
56 | 56 | When I press "Apply!" |
57 | 57 | Then I should not see "admin_user wants to create community Community for approval" |
58 | - When I go to the Control panel | |
58 | + And I go to admin_user's control panel | |
59 | 59 | And I follow "Manage my groups" |
60 | 60 | Then I should see "Community for approval" |
61 | 61 | |
... | ... | @@ -63,13 +63,13 @@ Feature: create community |
63 | 63 | Given I am logged in as admin |
64 | 64 | And feature "admin_must_approve_new_communities" is enabled on environment |
65 | 65 | When I create community "Community for approval" |
66 | - And I go to the Control panel | |
66 | + And I go to admin_user's control panel | |
67 | 67 | And I follow "Process requests" |
68 | 68 | And I should see "admin_user wants to create community Community for approval" |
69 | 69 | And I choose "Reject" |
70 | 70 | When I press "Apply!" |
71 | 71 | Then I should not see "admin_user wants to create community Community for approval" |
72 | - When I go to the Control panel | |
72 | + And I go to admin_user's control panel | |
73 | 73 | And I follow "Manage my groups" |
74 | 74 | Then I should not see "Community for approval" |
75 | 75 | |
... | ... | @@ -78,7 +78,7 @@ Feature: create community |
78 | 78 | And feature "admin_must_approve_new_communities" is enabled on environment |
79 | 79 | When I create community "Community for approval" |
80 | 80 | And I approve community "Community for approval" |
81 | - When I go to the Control panel | |
81 | + And I go to admin_user's control panel | |
82 | 82 | And I follow "Manage my groups" |
83 | 83 | Then I should see "Community for approval" |
84 | 84 | |
... | ... | @@ -87,6 +87,6 @@ Feature: create community |
87 | 87 | And feature "admin_must_approve_new_communities" is enabled on environment |
88 | 88 | When I create community "Community for approval" |
89 | 89 | And I reject community "Community for approval" |
90 | - When I go to the Control panel | |
90 | + And I go to admin_user's control panel | |
91 | 91 | And I follow "Manage my groups" |
92 | 92 | Then I should not see "Community for approval" | ... | ... |
features/delete_profile.feature
... | ... | @@ -13,9 +13,10 @@ Feature: delete profile |
13 | 13 | | sample-community | Sample Community | |
14 | 14 | And "Maria Silva" is a member of "Sample Community" |
15 | 15 | |
16 | + @selenium | |
16 | 17 | Scenario: deleting profile |
17 | 18 | Given I am logged in as "joaosilva" |
18 | - And I am on Joao Silva's control panel | |
19 | + And I am on joaosilva's control panel | |
19 | 20 | And I follow "Edit Profile" |
20 | 21 | And I follow "Delete profile" |
21 | 22 | Then I should see "Are you sure you want to delete this profile?" |
... | ... | @@ -31,24 +32,25 @@ Feature: delete profile |
31 | 32 | |
32 | 33 | Scenario: giving up of deleting profile |
33 | 34 | Given I am logged in as "joaosilva" |
34 | - And I am on Joao Silva's control panel | |
35 | + And I am on joaosilva's control panel | |
35 | 36 | And I follow "Edit Profile" |
36 | 37 | And I follow "Delete profile" |
37 | 38 | Then I should see "Are you sure you want to delete this profile?" |
38 | 39 | When I follow "No, I gave up" |
39 | - Then I should be on Joao Silva's profile | |
40 | + Then I should be on joaosilva's profile | |
40 | 41 | |
41 | 42 | Scenario: community admin can see link to delete profile |
42 | 43 | Given "Joao Silva" is admin of "Sample Community" |
43 | 44 | And I am logged in as "joaosilva" |
44 | - And I am on Sample Community's control panel | |
45 | + And I am on sample-community's control panel | |
45 | 46 | When I follow "Community Info and settings" |
46 | 47 | Then I should see "Delete profile" |
47 | 48 | |
49 | + @selenium | |
48 | 50 | Scenario: community admin deletes the community |
49 | 51 | Given "Joao Silva" is admin of "Sample Community" |
50 | 52 | And I am logged in as "joaosilva" |
51 | - And I am on Sample Community's control panel | |
53 | + And I am on sample-community's control panel | |
52 | 54 | And I follow "Community Info and settings" |
53 | 55 | And I follow "Delete profile" |
54 | 56 | Then I should see "Are you sure you want to delete this profile?" |
... | ... | @@ -69,17 +71,18 @@ Feature: delete profile |
69 | 71 | | sample-enterprise | Sample Enterprise | |
70 | 72 | And "Joao Silva" is admin of "Sample Enterprise" |
71 | 73 | And I am logged in as "joaosilva" |
72 | - And I am on Sample Enterprise's control panel | |
74 | + And I am on sample-enterprise's control panel | |
73 | 75 | When I follow "Enterprise Info and settings" |
74 | 76 | Then I should see "Delete profile" |
75 | 77 | |
78 | + @selenium | |
76 | 79 | Scenario: enterprise admin deletes the enterprise |
77 | 80 | Given the following enterprise |
78 | 81 | | identifier | name | |
79 | 82 | | sample-enterprise | Sample Enterprise | |
80 | 83 | And "Joao Silva" is admin of "Sample Enterprise" |
81 | 84 | And I am logged in as "joaosilva" |
82 | - And I am on Sample Enterprise's control panel | |
85 | + And I am on sample-enterprise's control panel | |
83 | 86 | When I follow "Enterprise Info and settings" |
84 | 87 | And I follow "Delete profile" |
85 | 88 | Then I should see "Are you sure you want to delete this profile?" |
... | ... | @@ -98,9 +101,10 @@ Feature: delete profile |
98 | 101 | And I go to /myprofile/sample-enterprise/profile_editor/destroy_profile |
99 | 102 | Then I should see "Access denied" |
100 | 103 | |
104 | + @selenium | |
101 | 105 | Scenario: environment admin deletes profile |
102 | 106 | Given I am logged in as admin |
103 | - And I am on Joao Silva's control panel | |
107 | + And I am on joaosilva's control panel | |
104 | 108 | And I follow "Edit Profile" |
105 | 109 | And I follow "Delete profile" |
106 | 110 | Then I should see "Are you sure you want to delete this profile?" | ... | ... |
features/edit_article.feature
... | ... | @@ -13,17 +13,17 @@ Feature: edit article |
13 | 13 | And I am logged in as "joaosilva" |
14 | 14 | |
15 | 15 | Scenario: create a folder |
16 | - Given I am on Joao Silva's control panel | |
16 | + Given I am on joaosilva's control panel | |
17 | 17 | And I follow "Manage Content" |
18 | 18 | And I follow "New content" |
19 | 19 | When I follow "Folder" |
20 | 20 | And I fill in "Title" with "My Folder" |
21 | 21 | And I press "Save" |
22 | - And I go to Joao Silva's control panel | |
22 | + And I go to joaosilva's control panel | |
23 | 23 | Then I should see "My Folder" |
24 | 24 | |
25 | 25 | Scenario: redirect to the created folder |
26 | - Given I am on Joao Silva's control panel | |
26 | + Given I am on joaosilva's control panel | |
27 | 27 | And I follow "Manage Content" |
28 | 28 | And I follow "New content" |
29 | 29 | When I follow "Folder" |
... | ... | @@ -33,29 +33,29 @@ Feature: edit article |
33 | 33 | And I should be on /joaosilva/my-folder |
34 | 34 | |
35 | 35 | Scenario: cancel button back to cms |
36 | - Given I go to the Control panel | |
36 | + Given I am on joaosilva's control panel | |
37 | 37 | And I follow "Manage Content" |
38 | 38 | And I follow "New content" |
39 | 39 | And I follow "Folder" |
40 | 40 | When I follow "Cancel" within ".main-block" |
41 | - Then I should be on Joao Silva's cms | |
41 | + Then I should be on joaosilva's cms | |
42 | 42 | |
43 | 43 | Scenario: display tag list field when creating event |
44 | - Given I go to the Control panel | |
44 | + Given I am on joaosilva's control panel | |
45 | 45 | And I follow "Manage Content" |
46 | 46 | And I follow "New content" |
47 | 47 | When I follow "Event" |
48 | 48 | Then I should see "Tag list" |
49 | 49 | |
50 | 50 | Scenario: display tag list field when creating folder |
51 | - Given I go to the Control panel | |
51 | + Given I am on joaosilva's control panel | |
52 | 52 | And I follow "Manage Content" |
53 | 53 | And I follow "New content" |
54 | 54 | When I follow "Folder" |
55 | 55 | Then I should see "Tag list" |
56 | 56 | |
57 | 57 | Scenario: create new article with tags |
58 | - Given I go to the Control panel | |
58 | + Given I am on joaosilva's control panel | |
59 | 59 | And I follow "Manage Content" |
60 | 60 | And I follow "New content" |
61 | 61 | When I follow "Text article with Textile markup language" |
... | ... | @@ -68,7 +68,7 @@ Feature: edit article |
68 | 68 | And I should see "bug" within "#article-tags a:last" |
69 | 69 | |
70 | 70 | Scenario: redirect to the created article |
71 | - Given I am on Joao Silva's control panel | |
71 | + Given I am on joaosilva's control panel | |
72 | 72 | And I follow "Manage Content" |
73 | 73 | When I follow "New content" |
74 | 74 | When I follow "Text article with visual editor" |
... | ... | @@ -79,62 +79,62 @@ Feature: edit article |
79 | 79 | |
80 | 80 | @selenium |
81 | 81 | Scenario: edit an article |
82 | - Given I am on Joao Silva's sitemap | |
83 | - When I follow "Save the whales" and wait | |
84 | - And I follow "Edit" and wait | |
82 | + Given I am on joaosilva's sitemap | |
83 | + When I follow "Save the whales" | |
84 | + And I follow "Edit" | |
85 | 85 | And I fill in "Title" with "My Article edited" |
86 | - And I press "Save" and wait | |
86 | + And I press "Save" | |
87 | 87 | Then I should be on /joaosilva/my-article-edited |
88 | 88 | |
89 | 89 | @selenium |
90 | 90 | Scenario: cancel button back to article when edit |
91 | - Given I am on Joao Silva's sitemap | |
92 | - When I follow "Save the whales" and wait | |
93 | - And I follow "Edit" and wait | |
94 | - And I follow "Cancel" and wait | |
91 | + Given I am on joaosilva's sitemap | |
92 | + When I follow "Save the whales" | |
93 | + And I follow "Edit" within "#article-actions" | |
94 | + And I follow "Cancel" | |
95 | 95 | Then I should be on /joaosilva/save-the-whales |
96 | 96 | |
97 | 97 | @selenium |
98 | 98 | Scenario: create an article inside a folder |
99 | - Given I am on Joao Silva's control panel | |
99 | + Given I am on joaosilva's control panel | |
100 | 100 | When I follow "Manage Content" |
101 | 101 | And I follow "New content" |
102 | - And I follow "Folder" and wait | |
102 | + And I follow "Folder" | |
103 | 103 | And I fill in "Title" with "My Folder" |
104 | - And I press "Save" and wait | |
104 | + And I press "Save" | |
105 | 105 | Then I should be on /joaosilva/my-folder |
106 | 106 | When I follow "New article" |
107 | - And I follow "Text article with visual editor" and wait | |
107 | + And I follow "Text article with visual editor" | |
108 | 108 | And I fill in "Title" with "My Article" |
109 | - And I press "Save" and wait | |
109 | + And I press "Save" | |
110 | 110 | Then I should see "My Article" |
111 | 111 | And I should be on /joaosilva/my-folder/my-article |
112 | 112 | |
113 | 113 | @selenium |
114 | 114 | Scenario: cancel button back to folder after giving up creating |
115 | - Given I am on Joao Silva's control panel | |
115 | + Given I am on joaosilva's control panel | |
116 | 116 | When I follow "Manage Content" |
117 | 117 | And I follow "New content" |
118 | - And I follow "Folder" and wait | |
118 | + And I follow "Folder" | |
119 | 119 | And I fill in "Title" with "My Folder" |
120 | - And I press "Save" and wait | |
120 | + And I press "Save" | |
121 | 121 | Then I should be on /joaosilva/my-folder |
122 | 122 | When I follow "New article" |
123 | - And I follow "Text article with visual editor" and wait | |
124 | - And I follow "Cancel" within ".no-boxes" and wait | |
123 | + And I follow "Text article with visual editor" | |
124 | + And I follow "Cancel" within ".no-boxes" | |
125 | 125 | Then I should be on /joaosilva/my-folder |
126 | 126 | |
127 | 127 | @selenium |
128 | 128 | Scenario: save and continue |
129 | 129 | Given I am on /joaosilva/save-the-whales |
130 | - And I follow "Edit" and wait | |
130 | + And I follow "Edit" | |
131 | 131 | When I fill in "Text" with "new text" |
132 | 132 | And I press "Save and continue" |
133 | 133 | Then the "Text" field should contain "new text" |
134 | 134 | And I should be on "Save the whales" edit page |
135 | 135 | |
136 | 136 | Scenario: save and continue when creating a new article |
137 | - Given I am on Joao Silva's control panel | |
137 | + Given I am on joaosilva's control panel | |
138 | 138 | When I follow "Manage Content" |
139 | 139 | And I follow "New content" |
140 | 140 | And I follow "Text article with visual editor" |
... | ... | @@ -147,16 +147,16 @@ Feature: edit article |
147 | 147 | |
148 | 148 | @selenium |
149 | 149 | Scenario: add a translation to an article |
150 | - Given I am on Joao Silva's sitemap | |
150 | + Given I am on joaosilva's sitemap | |
151 | 151 | And I follow "Save the whales" |
152 | 152 | Then I should not see "Add translation" |
153 | - And I follow "Edit" and wait | |
153 | + And I follow "Edit" | |
154 | 154 | And I select "English" from "Language" |
155 | - Then I press "Save" and wait | |
156 | - And I follow "Add translation" and wait | |
155 | + Then I press "Save" | |
156 | + And I follow "Add translation" | |
157 | 157 | And I fill in "Title" with "Mi neuvo artículo" |
158 | 158 | And I select "Español" from "Language" |
159 | - When I press "Save" and wait | |
159 | + When I press "Save" | |
160 | 160 | Then I should be on /joaosilva/mi-neuvo-articulo |
161 | 161 | And I should see "Translations" |
162 | 162 | |
... | ... | @@ -165,13 +165,13 @@ Feature: edit article |
165 | 165 | Given the following articles |
166 | 166 | | owner | name | language | |
167 | 167 | | joaosilva | Article in English | en | |
168 | - And I am on Joao Silva's sitemap | |
169 | - When I follow "Article in English" and wait | |
170 | - And I follow "Add translation" and wait | |
168 | + And I am on joaosilva's sitemap | |
169 | + When I follow "Article in English" | |
170 | + And I follow "Add translation" | |
171 | 171 | And I fill in "Title" with "Article in Portuguese" |
172 | - And I press "Save" and wait | |
172 | + And I press "Save" | |
173 | 173 | Then I should see "Language must be choosen" |
174 | 174 | When I select "Português" from "Language" |
175 | - And I press "Save" and wait | |
175 | + And I press "Save" | |
176 | 176 | Then I should not see "Language must be choosen" |
177 | 177 | And I should be on /joaosilva/article-in-portuguese | ... | ... |
features/edit_block_of_links.feature
... | ... | @@ -12,7 +12,7 @@ Feature: edit_block_of_links |
12 | 12 | | eddievedder | LinkListBlock | |
13 | 13 | And I am logged in as "eddievedder" |
14 | 14 | |
15 | - @selenium | |
15 | + @selenium-fixme | |
16 | 16 | Scenario: show the icon selector |
17 | 17 | Given I follow "Edit sideboxes" |
18 | 18 | And I follow "Edit" within ".link-list-block" | ... | ... |
features/edit_environment_templates.feature
... | ... | @@ -4,50 +4,46 @@ Feature: edit environment templates |
4 | 4 | |
5 | 5 | Background: |
6 | 6 | Given that the default environment have all profile templates |
7 | + And I am logged in as admin | |
8 | + And I am on the environment control panel | |
7 | 9 | |
10 | + @selenium | |
8 | 11 | Scenario: See links to edit all templates |
9 | - Given I am logged in as admin | |
10 | - When I follow "Administration" | |
11 | - And I follow "Profile templates" | |
12 | - Then I should see "Person template" link | |
13 | - And I should see "Community template" link | |
14 | - And I should see "Enterprise template" link | |
15 | - And I should see "Inactive Enterprise template" link | |
12 | + Given I follow "Profile templates" | |
13 | + Then I should see "Person template" | |
14 | + And I should see "Community template" | |
15 | + And I should see "Enterprise template" | |
16 | + And I should see "Inactive Enterprise template" | |
16 | 17 | |
18 | + @selenium | |
17 | 19 | Scenario: Go to control panel of person template |
18 | - Given I am logged in as admin | |
19 | - When I follow "Administration" | |
20 | - And I follow "Profile templates" | |
20 | + Given I follow "Profile templates" | |
21 | 21 | And I follow "Person template" |
22 | - Then I should be on Person template's control panel | |
22 | + Then I should be on colivre.net_person_template's control panel | |
23 | 23 | |
24 | + @selenium | |
24 | 25 | Scenario: Go to control panel of enterprise template |
25 | - Given I am logged in as admin | |
26 | - When I follow "Administration" | |
27 | - And I follow "Profile templates" | |
26 | + Given I follow "Profile templates" | |
28 | 27 | And I follow "Enterprise template" |
29 | - Then I should be on Enterprise template's control panel | |
28 | + Then I should be on colivre.net_enterprise_template's control panel | |
30 | 29 | |
30 | + @selenium | |
31 | 31 | Scenario: Go to control panel of inactive enterprise template |
32 | - Given I am logged in as admin | |
33 | - When I follow "Administration" | |
34 | - And I follow "Profile templates" | |
35 | - And I follow "Inactive enterprise template" | |
36 | - Then I should be on Inactive Enterprise template's control panel | |
32 | + Given I follow "Profile templates" | |
33 | + And I follow "Inactive Enterprise template" | |
34 | + Then I should be on colivre.net_inactive_enterprise_template's control panel | |
37 | 35 | |
36 | + @selenium | |
38 | 37 | Scenario: Go to control panel of community template |
39 | - Given I am logged in as admin | |
40 | - When I follow "Administration" | |
41 | - And I follow "Profile templates" | |
42 | - And I follow "Community template" | |
43 | - Then I should be on Community template's control panel | |
38 | + Given I follow "Profile templates" | |
39 | + When I follow "Community template" | |
40 | + Then I should be on colivre.net_community_template's control panel | |
44 | 41 | |
42 | + @selenium | |
45 | 43 | Scenario: Not see link to edit an unexistent template |
46 | - Given that the default environment have no Inactive Enterprise template | |
47 | - And I am logged in as admin | |
48 | - When I follow "Administration" | |
49 | - And I follow "Profile templates" | |
50 | - Then I should see "Person template" link | |
51 | - And I should see "Community template" link | |
52 | - And I should see "Enterprise template" link | |
53 | - And I should not see "Inactive enterprise template" link | |
44 | + Given I follow "Profile templates" | |
45 | + And that the default environment have no Inactive Enterprise template | |
46 | + Then I should see "Person template" | |
47 | + And I should see "Community template" | |
48 | + And I should see "Enterprise template" | |
49 | + And I should not see "Inactive enterprise template" | ... | ... |
features/edit_language_block.feature
... | ... | @@ -15,25 +15,25 @@ Feature: edit language of block |
15 | 15 | Scenario: display in all languages |
16 | 16 | Given I go to edit ArticleBlock of joaosilva |
17 | 17 | And I fill in "Custom title for this block" with "Block displayed" |
18 | - And I select "all languages" | |
18 | + And I select "all languages" from "Show for" | |
19 | 19 | And I press "Save" |
20 | - When I go to Jose Silva's homepage | |
20 | + When I go to joaosilva's homepage | |
21 | 21 | Then I should see "Block displayed" |
22 | 22 | |
23 | 23 | Scenario: display in the selected language |
24 | 24 | Given I go to edit LinkListBlock of joaosilva |
25 | 25 | And I fill in "Custom title for this block" with "Block displayed" |
26 | - And I select "English" | |
26 | + And I select "English" from "Show for" | |
27 | 27 | And I press "Save" |
28 | 28 | And my browser prefers English |
29 | - When I go to Jose Silva's homepage | |
29 | + When I go to joaosilva's homepage | |
30 | 30 | Then I should see "Block displayed" |
31 | 31 | |
32 | 32 | Scenario: not display in a not selected language |
33 | 33 | Given I go to edit LinkListBlock of joaosilva |
34 | 34 | And I fill in "Custom title for this block" with "Block not displayed" |
35 | - And I select "English" | |
35 | + And I select "English" from "Show for" | |
36 | 36 | And I press "Save" |
37 | 37 | And my browser prefers Portuguese |
38 | - When I go to Jose Silva's homepage | |
38 | + When I go to joaosilva's homepage | |
39 | 39 | Then I should not see "Block displayed" | ... | ... |
features/edit_profile.feature
... | ... | @@ -12,8 +12,8 @@ Feature: edit profile |
12 | 12 | | birth_date | |
13 | 13 | When I go to joao's control panel |
14 | 14 | And I follow "Edit Profile" |
15 | - And I select "November" | |
16 | - And I select "15" | |
15 | + And I select "November" from "profile_data_birth_date_2i" | |
16 | + And I select "15" from "profile_data_birth_date_3i" | |
17 | 17 | And I press "Save" |
18 | 18 | Then I should see "Birth date is invalid" |
19 | 19 | And I should not see "Birth date can't be blank" |
... | ... | @@ -24,8 +24,8 @@ Feature: edit profile |
24 | 24 | | birth_date | |
25 | 25 | When I go to joao's control panel |
26 | 26 | And I follow "Edit Profile" |
27 | - And I select "November" | |
28 | - And I select "15" | |
27 | + And I select "November" from "profile_data_birth_date_2i" | |
28 | + And I select "15" from "profile_data_birth_date_3i" | |
29 | 29 | And I press "Save" |
30 | 30 | Then I should see "Birth date is invalid" |
31 | 31 | And I should not see "Birth date can't be blank" |
... | ... | @@ -36,9 +36,9 @@ Feature: edit profile |
36 | 36 | | birth_date | |
37 | 37 | When I go to joao's control panel |
38 | 38 | And I follow "Edit Profile" |
39 | - And I select "November" | |
40 | - And I select "15" | |
41 | - And I select "1980" | |
39 | + And I select "November" from "profile_data_birth_date_2i" | |
40 | + And I select "15" from "profile_data_birth_date_3i" | |
41 | + And I select "1980" from "profile_data_birth_date_1i" | |
42 | 42 | And I press "Save" |
43 | 43 | Then I should not see "Birth date is invalid" |
44 | 44 | And I should not see "Birth date is mandatory" |
... | ... | @@ -49,9 +49,9 @@ Feature: edit profile |
49 | 49 | | birth_date | |
50 | 50 | When I go to joao's control panel |
51 | 51 | And I follow "Edit Profile" |
52 | - And I select "November" | |
53 | - And I select "15" | |
54 | - And I select "1980" | |
52 | + And I select "November" from "profile_data_birth_date_2i" | |
53 | + And I select "15" from "profile_data_birth_date_3i" | |
54 | + And I select "1980" from "profile_data_birth_date_1i" | |
55 | 55 | And I press "Save" |
56 | 56 | Then I should not see "Birth date is invalid" |
57 | 57 | And I should not see "Birth date is mandatory" |
... | ... | @@ -62,11 +62,11 @@ Feature: edit profile |
62 | 62 | | identifier | name | owner | |
63 | 63 | | o-rappa | O Rappa | joao | |
64 | 64 | And feature "enable_organization_url_change" is enabled on environment |
65 | - When I go to O Rappa's control panel | |
66 | - And I follow "Community Info and settings" and wait | |
67 | - Then the "#identifier-change-confirmation" should not be visible | |
65 | + When I go to o-rappa's control panel | |
66 | + And I follow "Community Info and settings" | |
67 | + And I should not see "identifier-change-confirmation" | |
68 | 68 | When I fill in "Address" with "banda-o-rappa" |
69 | - Then the "#identifier-change-confirmation" should be visible | |
69 | + And I should see "identifier-change-confirmation" | |
70 | 70 | |
71 | 71 | @selenium |
72 | 72 | Scenario: Confirm url change |
... | ... | @@ -74,12 +74,12 @@ Feature: edit profile |
74 | 74 | | identifier | name | owner | |
75 | 75 | | o-rappa | O Rappa | joao | |
76 | 76 | And feature "enable_organization_url_change" is enabled on environment |
77 | - When I go to O Rappa's control panel | |
78 | - And I follow "Community Info and settings" and wait | |
77 | + When I go to o-rappa's control panel | |
78 | + And I follow "Community Info and settings" | |
79 | 79 | When I fill in "Address" with "banda-o-rappa" |
80 | - Then the "#identifier-change-confirmation" should be visible | |
80 | + Then I should see "identifier-change-confirmation" | |
81 | 81 | When I follow "Yes" |
82 | - Then the "#identifier-change-confirmation" should not be visible | |
82 | + Then "identifier-change-confirmation" should not be visible within "profile-identifier-formitem" | |
83 | 83 | |
84 | 84 | @selenium |
85 | 85 | Scenario: Cancel url change |
... | ... | @@ -87,9 +87,9 @@ Feature: edit profile |
87 | 87 | | identifier | name | owner | |
88 | 88 | | o-rappa | O Rappa | joao | |
89 | 89 | And feature "enable_organization_url_change" is enabled on environment |
90 | - When I go to O Rappa's control panel | |
91 | - And I follow "Community Info and settings" and wait | |
90 | + When I go to o-rappa's control panel | |
91 | + And I follow "Community Info and settings" | |
92 | 92 | When I fill in "Address" with "banda-o-rappa" |
93 | - Then the "#identifier-change-confirmation" should be visible | |
93 | + Then I should see "identifier-change-confirmation" | |
94 | 94 | When I follow "No" |
95 | - Then the "#identifier-change-confirmation" should not be visible | |
95 | + Then "identifier-change-confirmation" should not be visible within "profile-identifier-formitem" | ... | ... |
features/environment_name.feature
... | ... | @@ -3,6 +3,7 @@ Feature: setting environment name |
3 | 3 | I want to change the name of the environment |
4 | 4 | So that it appears in the window's title bar |
5 | 5 | |
6 | + @selenium-fixme | |
6 | 7 | Scenario: setting environment name through administration panel |
7 | 8 | Given I am logged in as admin |
8 | 9 | When I follow "Administration" | ... | ... |