aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <msabate@suse.com>2024-03-13 18:03:43 +0100
committerMiquel Sabaté Solà <msabate@suse.com>2024-03-13 18:03:43 +0100
commita7791635aa98f012d35f97c3c5288494bbb28e38 (patch)
treebad987e6b4d10ad2f7cd02e40658d464907595ee /test
downloadoperum-a7791635aa98f012d35f97c3c5288494bbb28e38.tar.gz
operum-a7791635aa98f012d35f97c3c5288494bbb28e38.zip
Initial commit
Signed-off-by: Miquel Sabaté Solà <msabate@suse.com>
Diffstat (limited to 'test')
-rw-r--r--test/application_system_test_case.rb26
-rw-r--r--test/controllers/exports_controller_test.rb24
-rw-r--r--test/fixtures/action_text/rich_texts.yml4
-rw-r--r--test/fixtures/comments.yml2
-rw-r--r--test/fixtures/files/all.uoc.tex9
-rw-r--r--test/fixtures/searches.yml4
-rw-r--r--test/fixtures/tag_references.yml15
-rw-r--r--test/fixtures/tags.yml5
-rw-r--r--test/fixtures/things.yml39
-rw-r--r--test/fixtures/users.yml4
-rw-r--r--test/models/comment_test.rb18
-rw-r--r--test/models/search_test.rb90
-rw-r--r--test/models/tag_test.rb16
-rw-r--r--test/models/thing_test.rb95
-rw-r--r--test/models/user_test.rb28
-rw-r--r--test/system/comments_test.rb103
-rw-r--r--test/system/exports_test.rb27
-rw-r--r--test/system/licenses_test.rb11
-rw-r--r--test/system/searches_test.rb123
-rw-r--r--test/system/sessions_test.rb27
-rw-r--r--test/system/shared_searches_test.rb34
-rw-r--r--test/system/tags_test.rb40
-rw-r--r--test/system/things_test.rb102
-rw-r--r--test/test_helper.rb18
24 files changed, 864 insertions, 0 deletions
diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb
new file mode 100644
index 0000000..eaa28b0
--- /dev/null
+++ b/test/application_system_test_case.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+ driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]
+
+ # Sign in with the default user.
+ def sign_in!
+ visit new_sessions_url
+
+ fill_in I18n.t('activerecord.attributes.user.username'), with: users(:user).username
+ fill_in I18n.t('activerecord.attributes.user.password'), with: '12341234'
+ click_on I18n.t('sessions.sign-in')
+
+ assert_text I18n.t('searches.home')
+ end
+
+ # Sign out the current user if it's already signed in, otherwise do nothing.
+ def sign_out_maybe!
+ click_on I18n.t('sessions.sign-out')
+ assert_text I18n.t('sessions.title')
+ rescue Capybara::ElementNotFound
+ # We were not logged in, do nothing.
+ end
+end
diff --git a/test/controllers/exports_controller_test.rb b/test/controllers/exports_controller_test.rb
new file mode 100644
index 0000000..42ed1a2
--- /dev/null
+++ b/test/controllers/exports_controller_test.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class ExportsControllerTest < ActionDispatch::IntegrationTest
+ # We need the session to be initialized as a signed in user.
+ setup { post sessions_url, params: { username: users(:user).username, password: '12341234' } }
+
+ test 'csv: works' do
+ get search_exports_url(0, format: 'csv')
+
+ body = @response.body.split("\n")
+ assert body.size == 2
+ assert body.first.split(',')[0] == things(:thing2).target
+ assert body.last.split(',')[0] == things(:thing1).target
+
+ assert @response.media_type == 'text/csv'
+ end
+
+ test 'uoc: works' do
+ get search_exports_url(0, format: 'uoc')
+
+ assert @response.body == file_fixture('all.uoc.tex').read
+ assert @response.media_type == 'application/x-tex'
+ end
+end
diff --git a/test/fixtures/action_text/rich_texts.yml b/test/fixtures/action_text/rich_texts.yml
new file mode 100644
index 0000000..8c95217
--- /dev/null
+++ b/test/fixtures/action_text/rich_texts.yml
@@ -0,0 +1,4 @@
+comment1:
+ record: comment1 (Comment)
+ name: content
+ body: <p>Such awesome content from Miquel</p>
diff --git a/test/fixtures/comments.yml b/test/fixtures/comments.yml
new file mode 100644
index 0000000..f61437d
--- /dev/null
+++ b/test/fixtures/comments.yml
@@ -0,0 +1,2 @@
+comment1:
+ thing_id: <%= ActiveRecord::FixtureSet.identify(:thing1) %>
diff --git a/test/fixtures/files/all.uoc.tex b/test/fixtures/files/all.uoc.tex
new file mode 100644
index 0000000..227a2bb
--- /dev/null
+++ b/test/fixtures/files/all.uoc.tex
@@ -0,0 +1,9 @@
+\chapter{Bibliografia}
+
+{\setlength{\parskip}{-0.3cm}
+
+\hypertarget{target2}{\textsc{Sabaté}, Miquel; \textsc{Nom} (eds.) (2024). \emph{This is a 2}. Dins de \emph{Some other thing}, 22-24. This is a note 2. Publisher 2, Address 2: 2024.}
+
+\\~\\\hypertarget{target1}{\textsc{Sabaté}, Miquel; \textsc{Smith}, John; \textsc{cognom2}, Nom cognom1; \textsc{cognom3 cognom4}, Nom (2024). \emph{This is a title 1}. Dins de \emph{Some other thing}, 22-24. This is a note 1. Publisher 1. [\url{http://example.com}]. [Última data de consulta: 24 de febrer de 2024].}
+
+}
diff --git a/test/fixtures/searches.yml b/test/fixtures/searches.yml
new file mode 100644
index 0000000..ffc7a28
--- /dev/null
+++ b/test/fixtures/searches.yml
@@ -0,0 +1,4 @@
+search1:
+ name: 'search1'
+ body: "tag:\"tag1\""
+ user_id: <%= ActiveRecord::FixtureSet.identify(:user) %>
diff --git a/test/fixtures/tag_references.yml b/test/fixtures/tag_references.yml
new file mode 100644
index 0000000..d6267d5
--- /dev/null
+++ b/test/fixtures/tag_references.yml
@@ -0,0 +1,15 @@
+thing1tag1:
+ tag_id: <%= ActiveRecord::FixtureSet.identify(:tag1) %>
+ taggable: thing1 (Thing)
+
+thing1tag2:
+ tag_id: <%= ActiveRecord::FixtureSet.identify(:tag2) %>
+ taggable: thing1 (Thing)
+
+thing2tag1:
+ tag_id: <%= ActiveRecord::FixtureSet.identify(:tag1) %>
+ taggable: thing2 (Thing)
+
+comment1tag1:
+ tag_id: <%= ActiveRecord::FixtureSet.identify(:tag1) %>
+ taggable: comment1 (Comment)
diff --git a/test/fixtures/tags.yml b/test/fixtures/tags.yml
new file mode 100644
index 0000000..1e0ce52
--- /dev/null
+++ b/test/fixtures/tags.yml
@@ -0,0 +1,5 @@
+tag1:
+ name: 'tag1'
+
+tag2:
+ name: 'tag2'
diff --git a/test/fixtures/things.yml b/test/fixtures/things.yml
new file mode 100644
index 0000000..069cf85
--- /dev/null
+++ b/test/fixtures/things.yml
@@ -0,0 +1,39 @@
+thing1:
+ target: 'target1'
+ title: 'This is a title 1'
+ publisher: 'Publisher 1'
+ authors: 'Miquel Sabaté, John Smith, Nom cognom1 cognom2, Nom _cognom3 cognom4_'
+ editors: false
+ address:
+ year: 2024
+ url: 'http://example.com'
+ location: 'Somewhere'
+ insideof: 'Some other thing'
+ pages: '22-24'
+ note: 'This is a note 1'
+ rate: 5
+ status: <%= Thing.statuses[:read] %>
+ kind: <%= Thing.kinds[:novel] %>
+ access: 2024-02-24 17:24:12
+ bought_at: 2024-02-24 17:24:12
+ user_id: <%= ActiveRecord::FixtureSet.identify(:user) %>
+
+thing2:
+ target: 'target2'
+ title: 'This is a 2'
+ publisher: 'Publisher 2'
+ authors: 'Miquel Sabaté, Nom'
+ editors: true
+ address: 'Address 2'
+ year: 2024
+ url: 'http://example.com'
+ location: 'Somewhere'
+ insideof: 'Some other thing'
+ pages: '22-24'
+ note: 'This is a note 2'
+ rate: 8
+ status: <%= Thing.statuses[:read] %>
+ kind: <%= Thing.kinds[:poetry] %>
+ access: 2024-02-24 17:24:12
+ bought_at: 2024-02-24 17:24:12
+ user_id: <%= ActiveRecord::FixtureSet.identify(:user) %>
diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml
new file mode 100644
index 0000000..66baf92
--- /dev/null
+++ b/test/fixtures/users.yml
@@ -0,0 +1,4 @@
+user:
+ username: user
+ password_digest: <%= BCrypt::Password.create("12341234", cost: 4) %>
+ last_search_id: null
diff --git a/test/models/comment_test.rb b/test/models/comment_test.rb
new file mode 100644
index 0000000..087963a
--- /dev/null
+++ b/test/models/comment_test.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class CommentTest < ActiveSupport::TestCase
+ test 'content is present' do
+ comment = Comment.new(thing_id: things(:thing1).id)
+ assert_raise(ActiveRecord::RecordInvalid) { comment.save! }
+
+ comment.content = 'whatever'
+ assert_difference('Comment.count') { comment.save! }
+ end
+
+ test 'has many tags through tag_references' do
+ comment = comments(:comment1)
+ assert comment.tags.size == 1
+ end
+end
diff --git a/test/models/search_test.rb b/test/models/search_test.rb
new file mode 100644
index 0000000..9614bc0
--- /dev/null
+++ b/test/models/search_test.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class SearchTest < ActiveSupport::TestCase
+ test 'name and body have to be present and unique' do
+ search = Search.new(user_id: users(:user).id)
+ assert_raise(ActiveRecord::RecordInvalid) { search.save! }
+
+ search.name = 'new search'
+ assert_raise(ActiveRecord::RecordInvalid) { search.save! }
+
+ search.name = nil
+ search.body = 'body'
+ assert_raise(ActiveRecord::RecordInvalid) { search.save! }
+
+ search.name = searches(:search1).name
+ assert_raise(ActiveRecord::RecordInvalid) { search.save! }
+
+ search.name = 'another'
+ search.body = searches(:search1).body
+ assert_raise(ActiveRecord::RecordInvalid) { search.save! }
+
+ search.body = 'another body'
+ assert_difference('Search.count') { search.save! }
+ end
+
+ ##
+ # Results.
+
+ test 'returns all things when an empty body is given' do
+ res = Search.new.results
+
+ assert res[:things].size == 2
+ assert res[:things][0][:target] == things(:thing2).target
+ assert res[:things][1][:target] == things(:thing1).target
+ end
+
+ test 'returns everything matching a specific tag' do
+ res = Search.new(body: "tag:'#{tags(:tag1).name}'").results
+
+ assert res[:things].size == 2
+ assert res[:things][0][:target] == things(:thing2).target
+ assert res[:things][1][:target] == things(:thing1).target
+ assert res[:comments].size == 1
+ assert res[:comments][0][:id] == comments(:comment1).id
+ end
+
+ test 'returns everything matching two tags' do
+ res = Search.new(body: "tag:'#{tags(:tag1).name}' tag:'#{tags(:tag2).name}'").results
+
+ assert res[:things].size == 1
+ assert res[:things][0][:target] == things(:thing1).target
+ assert res[:comments].empty?
+ end
+
+ test 'returns everything matching a given text' do
+ res = Search.new(body: 'Miquel').results
+
+ assert res[:things].size == 2
+ assert res[:things][0][:target] == things(:thing2).target
+ assert res[:things][1][:target] == things(:thing1).target
+ assert res[:comments].size == 1
+ assert res[:comments][0][:id] == comments(:comment1).id
+ end
+
+ test 'returns everything matching two tags and a given text' do
+ res = Search.new(body: "Miquel tag:'#{tags(:tag1).name}' tag:'#{tags(:tag2).name}'").results
+
+ assert res[:things].size == 1
+ assert res[:things][0][:target] == things(:thing1).target
+ assert res[:comments].empty?
+ end
+
+ test 'returns everything matching a given compound text' do
+ res = Search.new(body: 'some other').results
+
+ assert res[:things].size == 2
+ assert res[:things][0][:target] == things(:thing2).target
+ assert res[:things][1][:target] == things(:thing1).target
+ assert res[:comments].empty?
+ end
+
+ test 'returns an empty result with unknown fields' do
+ res = Search.new(body: 'whatever:"unknown"').results
+
+ assert res[:things].empty?
+ assert res[:comments].empty?
+ end
+end
diff --git a/test/models/tag_test.rb b/test/models/tag_test.rb
new file mode 100644
index 0000000..dafb8e4
--- /dev/null
+++ b/test/models/tag_test.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class TagTest < ActiveSupport::TestCase
+ test 'name is present and unique' do
+ tag = Tag.new
+ assert_raise(ActiveRecord::RecordInvalid) { tag.save! }
+
+ tag = Tag.new(name: tags(:tag1).name)
+ assert_raise(ActiveRecord::RecordInvalid) { tag.save! }
+
+ tag.name = 'another'
+ assert_difference('Tag.count') { tag.save! }
+ end
+end
diff --git a/test/models/thing_test.rb b/test/models/thing_test.rb
new file mode 100644
index 0000000..0b3961e
--- /dev/null
+++ b/test/models/thing_test.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class ThingTest < ActiveSupport::TestCase
+ test 'validates presence' do
+ assert_raise(ActiveRecord::RecordInvalid) { Thing.new.save! }
+
+ # Missing 'title'
+ assert_raise(ActiveRecord::RecordInvalid) do
+ Thing.new(target: 'target', authors: 'Author',
+ user_id: users(:user).id, rate: 5,
+ status: Thing.statuses[:read], kind: Thing.kinds[:novel]).save!
+ end
+
+ # Missing 'target'
+ assert_raise(ActiveRecord::RecordInvalid) do
+ Thing.new(title: 'title', authors: 'Author',
+ user_id: users(:user).id, rate: 5,
+ status: Thing.statuses[:read], kind: Thing.kinds[:novel]).save!
+ end
+
+ # Missing 'authors'
+ assert_raise(ActiveRecord::RecordInvalid) do
+ Thing.new(title: 'title', target: 'target',
+ user_id: users(:user).id, rate: 5,
+ status: Thing.statuses[:read], kind: Thing.kinds[:novel]).save!
+ end
+
+ # Valid!
+ assert_difference('Thing.count') do
+ Thing.new(title: 'title', target: 'target', authors: 'Author',
+ user_id: users(:user).id, rate: 5,
+ status: Thing.statuses[:read], kind: Thing.kinds[:novel]).save!
+ end
+ end
+
+ test "'rate' has to be between 0 and 10" do
+ thing = things(:thing1)
+
+ thing.rate = -1
+ assert_raise(ActiveRecord::RecordInvalid) { thing.save! }
+
+ thing.rate = 11
+ assert_raise(ActiveRecord::RecordInvalid) { thing.save! }
+
+ thing.rate = 5
+ thing.save!
+ end
+
+ test "'status' has to have a value as defined by its enum" do
+ thing = things(:thing1)
+
+ thing.status = 'whatever'
+ assert_raise(ActiveRecord::RecordInvalid) { thing.save! }
+
+ thing.status = Thing.statuses[:tobepublished]
+ thing.save!
+ end
+
+ test "'kind' has to have a value as defined by its enum" do
+ thing = things(:thing1)
+
+ thing.kind = 'whatever'
+ assert_raise(ActiveRecord::RecordInvalid) { thing.save! }
+
+ thing.kind = Thing.kinds[:other]
+ thing.save!
+ end
+
+ test 'title and target must be unique' do
+ thing = things(:thing1).dup
+
+ thing.title = 'another'
+ assert_raise(ActiveRecord::RecordInvalid) { thing.save! }
+
+ thing.target = 'also another'
+ thing.title = things(:thing1).title
+ assert_raise(ActiveRecord::RecordInvalid) { thing.save! }
+
+ thing.target = 'also another'
+ thing.title = 'now for real'
+ assert_difference('Thing.count') { thing.save! }
+ end
+
+ test 'has many comments' do
+ thing = things(:thing1)
+ assert thing.comments.size == 1
+ end
+
+ test 'has many tags through tag_references' do
+ thing = things(:thing1)
+ assert thing.tags.size == 2
+ end
+end
diff --git a/test/models/user_test.rb b/test/models/user_test.rb
new file mode 100644
index 0000000..6ff5e19
--- /dev/null
+++ b/test/models/user_test.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'test_helper'
+
+class UserTest < ActiveSupport::TestCase
+ test 'has to provide username and password' do
+ user = User.new
+ assert_raise(ActiveRecord::RecordInvalid) { user.save! }
+
+ user.username = 'whatever'
+ assert_raise(ActiveRecord::RecordInvalid) { user.save! }
+
+ user.password = '1234'
+ user.password_confirmation = '12345'
+ assert_raise(ActiveRecord::RecordInvalid) { user.save! }
+
+ user.password_confirmation = '1234'
+ assert_difference('User.count') do
+ user.save!
+ end
+ end
+
+ test 'username has to be unique' do
+ user = User.new(username: users(:user).username,
+ password: '1234', password_confirmation: '1234')
+ assert_raise(ActiveRecord::RecordInvalid) { user.save! }
+ end
+end
diff --git a/test/system/comments_test.rb b/test/system/comments_test.rb
new file mode 100644
index 0000000..b2490b4
--- /dev/null
+++ b/test/system/comments_test.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+require 'application_system_test_case'
+
+class CommentsTest < ApplicationSystemTestCase
+ setup { sign_in! }
+
+ ##
+ # In things#show
+
+ test 'things#show: the hidden form is shown when clicking the proper button' do
+ visit thing_url(things(:thing1))
+
+ click_on I18n.t('comments.new')
+ assert_text I18n.t('tags.new-action'), count: 1
+
+ click_on I18n.t('general.cancel')
+ assert_text I18n.t('tags.new-action'), count: 0
+ end
+
+ test 'things#show: you can add a new comment' do
+ visit thing_url(things(:thing1))
+
+ click_on I18n.t('comments.new')
+ find(:css, '#comment_content').set('a new comment')
+ find("#comment_tag_ids_#{tags(:tag1).id}").click
+ find("#comment_tag_ids_#{tags(:tag2).id}").click
+
+ click_on I18n.t('helpers.submit.create')
+
+ assert_text "#{I18n.t('comments.title')} #2"
+ assert_text 'a new comment'
+ assert_text "#{I18n.t('tags.title')}: #{tags(:tag1).name}, #{tags(:tag2).name}"
+ assert page.current_path == thing_path(things(:thing1))
+ end
+
+ test 'things#show: you can update a comment' do
+ visit thing_url(things(:thing1))
+
+ click_on I18n.t('general.edit').capitalize
+ find(:css, '#comment_content').set('updated comment')
+
+ find("#comment_#{comments(:comment1).id} input[type=submit]").click
+ assert_text 'updated comment'
+ assert page.current_path == thing_path(things(:thing1))
+ end
+
+ test 'things#show: you can delete a comment' do
+ visit thing_url(things(:thing1))
+
+ all('.delete-comment').last.click
+ assert_text I18n.t('comments.none')
+ assert page.current_path == thing_path(things(:thing1))
+ end
+
+ ##
+ # In things#edit
+
+ test 'things#edit: the hidden form is shown when clicking the proper button' do
+ visit edit_thing_url(things(:thing1))
+
+ click_on I18n.t('comments.new')
+ assert_text I18n.t('tags.new-action'), count: 2
+
+ click_on I18n.t('general.cancel')
+ assert_text I18n.t('tags.new-action'), count: 1
+ end
+
+ test 'things#edit: you can add a new comment' do
+ visit edit_thing_url(things(:thing1))
+
+ click_on I18n.t('comments.new')
+ find(:css, '#comment_content').set('a new comment')
+ find("#comment_tag_ids_#{tags(:tag1).id}").click
+ find("#comment_tag_ids_#{tags(:tag2).id}").click
+
+ click_on I18n.t('helpers.submit.create')
+
+ assert_text "#{I18n.t('comments.title')} #2"
+ assert_text 'a new comment'
+ assert_text "#{I18n.t('tags.title')}: #{tags(:tag1).name}, #{tags(:tag2).name}"
+ assert page.current_path == edit_thing_path(things(:thing1))
+ end
+
+ test 'things#edit: you can update a comment' do
+ visit edit_thing_url(things(:thing1))
+
+ click_on I18n.t('general.edit').capitalize
+ find(:css, '#comment_content').set('updated comment')
+
+ find("#comment_#{comments(:comment1).id} input[type=submit]").click
+ assert_text 'updated comment'
+ assert page.current_path == edit_thing_path(things(:thing1))
+ end
+
+ test 'things#edit: you can delete a comment' do
+ visit edit_thing_url(things(:thing1))
+
+ all('.delete-comment').last.click
+ assert_text I18n.t('comments.none')
+ assert page.current_path == edit_thing_path(things(:thing1))
+ end
+end
diff --git a/test/system/exports_test.rb b/test/system/exports_test.rb
new file mode 100644
index 0000000..b324321
--- /dev/null
+++ b/test/system/exports_test.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'application_system_test_case'
+
+class ExportsTest < ApplicationSystemTestCase
+ setup do
+ sign_in!
+ end
+
+ test 'can access exports from the hidden menu' do
+ find('#toggle-hidden-global-menu').click
+ assert_text I18n.t('searches.export.action')
+
+ click_on I18n.t('searches.export.action')
+ assert_text I18n.t('searches.export.note-msg')
+ assert page.current_path == new_search_exports_path(0)
+ end
+
+ test 'can export using multiple formats' do
+ visit new_search_exports_path(0)
+
+ assert find('#export-format-button')[:href].ends_with?('/searches/0/exports.csv')
+
+ find('#export-select-format').select('UOC')
+ assert find('#export-format-button')[:href].ends_with?('/searches/0/exports.uoc')
+ end
+end
diff --git a/test/system/licenses_test.rb b/test/system/licenses_test.rb
new file mode 100644
index 0000000..1e26664
--- /dev/null
+++ b/test/system/licenses_test.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'application_system_test_case'
+
+class LicensesTest < ApplicationSystemTestCase
+ test 'can reach #show without login' do
+ visit license_url
+
+ assert_text 'AGPLv3'
+ end
+end
diff --git a/test/system/searches_test.rb b/test/system/searches_test.rb
new file mode 100644
index 0000000..a400e71
--- /dev/null
+++ b/test/system/searches_test.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+require 'application_system_test_case'
+
+class SearchesTest < ApplicationSystemTestCase
+ setup do
+ # All actions will require the user to be logged in.
+ sign_in!
+ end
+
+ test 'root url is searches#index, which contains all things plus the tabs we expect' do
+ visit root_url
+
+ # All searches are listed.
+ assert_text I18n.t('searches.home')
+ searches.each { |s| assert_text s.name }
+
+ # All things are listed
+ things.each { |t| assert_text t.title }
+ end
+
+ test 'the hidden menu should allow us to go into the searches#new url' do
+ find('#toggle-hidden-global-menu').click
+ assert_text I18n.t('searches.title')
+
+ click_on I18n.t('searches.object')
+ assert find('#search_body')
+ assert page.current_path == new_search_path
+ end
+
+ test 'can perform a new search' do
+ visit new_search_url
+
+ # Fill in the body input and press enter, otherwise the javascript
+ # controller won't fire up.
+ fill_in 'search_body', with: 'Miquel'
+ find('#search_body').native.send_keys(:return)
+
+ # It's actually a pretty generous search: it should give us all thing and a
+ # comment.
+ assert_text I18n.t('searches.save')
+ assert_text things(:thing1).title
+ assert_text things(:thing2).title
+ assert_text I18n.t('comments.title')
+ assert_text tags(:tag1).name
+ end
+
+ test 'can save a new search' do
+ visit new_search_url
+
+ # Fill in the body input and press enter, otherwise the javascript
+ # controller won't fire up.
+ fill_in 'search_body', with: 'Autor'
+ find('#search_body').native.send_keys(:return)
+
+ # Hit the save button so the hidden form appears.
+ assert_text I18n.t('searches.save')
+ find('#save-search').click
+ assert_text I18n.t('searches.public')
+
+ fill_in 'Name', with: 'Nova cerca'
+ click_on I18n.t('helpers.submit.create')
+
+ assert_text 'Nova cerca'
+ assert page.current_path == search_path(Search.find_by(name: 'Nova cerca'))
+ end
+
+ test 'can edit a search that is not the Home' do
+ # Home cannot be edited.
+ find('#toggle-hidden-global-menu').click
+ assert_selector 'a', text: I18n.t('general.edit'), count: 0
+
+ # Select search1
+ click_on searches(:search1).name
+ assert_selector 'a', text: things(:thing1).title, count: 2
+ find('#toggle-hidden-global-menu').click
+
+ # It can be edited!
+ assert_text I18n.t('general.edit')
+ click_on I18n.t('general.edit')
+
+ # If you click on it, you will be on the edit page for it.
+ assert find('#search_body')
+ assert page.current_path == edit_search_path(searches(:search1))
+ end
+
+ test 'edit an existing search works' do
+ visit edit_search_url(searches(:search1))
+
+ find('#search_body').native.send_keys(:return)
+
+ # Hit the save button so the hidden form appears.
+ assert_text I18n.t('searches.save')
+ find('#save-search').click
+ assert_text I18n.t('searches.public')
+
+ # Update the name.
+ fill_in 'Name', with: 'Nova cerca'
+ click_on I18n.t('helpers.submit.update')
+
+ # We have been redirected to search#show, and the name has been refreshed.
+ assert_selector 'a', text: searches(:search1).name, count: 0
+ assert_text 'Nova cerca'
+ assert page.current_path == search_path(searches(:search1))
+ end
+
+ test 'can delete a search that is not the Home' do
+ # Home cannot be deleted.
+ find('#toggle-hidden-global-menu').click
+ assert_selector 'a', text: I18n.t('general.delete'), count: 0
+
+ # Select search1
+ click_on searches(:search1).name
+ assert_selector 'a', text: things(:thing1).title, count: 2
+ find('#toggle-hidden-global-menu').click
+
+ # It can be deleted!
+ assert_text I18n.t('general.delete')
+ accept_alert { click_on I18n.t('general.delete') }
+ assert_selector 'a', text: searches(:search1).name, count: 0
+ assert Search.none?
+ end
+end
diff --git a/test/system/sessions_test.rb b/test/system/sessions_test.rb
new file mode 100644
index 0000000..2d01eef
--- /dev/null
+++ b/test/system/sessions_test.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'application_system_test_case'
+
+class SessionsTest < ApplicationSystemTestCase
+ test 'logs in successfully' do
+ sign_in!
+ end
+
+ test 'fails to log in with wrong password' do
+ visit new_sessions_url
+
+ fill_in I18n.t('activerecord.attributes.user.username'), with: users(:user).username
+ fill_in I18n.t('activerecord.attributes.user.password'), with: 'I AM ERROR'
+ click_on I18n.t('sessions.sign-in')
+
+ assert_text I18n.t('sessions.wrong-credentials')
+ end
+
+ test 'logs out successfully' do
+ sign_in!
+
+ click_on I18n.t('sessions.sign-out')
+
+ assert_text I18n.t('sessions.title')
+ end
+end
diff --git a/test/system/shared_searches_test.rb b/test/system/shared_searches_test.rb
new file mode 100644
index 0000000..0cfc4bd
--- /dev/null
+++ b/test/system/shared_searches_test.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'application_system_test_case'
+
+class SharedSearchesTest < ApplicationSystemTestCase
+ test 'can access shared_searches#index from the hidden menu' do
+ sign_in!
+
+ find('#toggle-hidden-global-menu').click
+ assert_text I18n.t('searches.shared.title').downcase
+
+ click_on I18n.t('searches.shared.title').downcase
+ assert_text I18n.t('searches.shared.none')
+ end
+
+ test 'cannot access shared_searches#index if not logged in' do
+ sign_out_maybe!
+
+ visit shared_searches_path
+ assert_text I18n.t('sessions.title')
+ assert page.current_path == new_sessions_path
+ end
+
+ test 'shared_searches#show gives us the expected results' do
+ # NOTE: not logged in!
+
+ searches(:search1).update!(shared: true)
+
+ visit search_shared_path(searches(:search1))
+ assert_text things(:thing1).title
+ assert_text things(:thing2).title
+ assert_text I18n.t('comments.title')
+ end
+end
diff --git a/test/system/tags_test.rb b/test/system/tags_test.rb
new file mode 100644
index 0000000..1ee83a9
--- /dev/null
+++ b/test/system/tags_test.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'application_system_test_case'
+
+class SharedSearchesTest < ApplicationSystemTestCase
+ setup { sign_in! }
+
+ test 'lists all the tags' do
+ visit tags_url
+
+ tags.each { |t| assert_text t.name }
+ end
+
+ test 'can create a new tag' do
+ visit new_tag_url
+
+ fill_in I18n.t('activerecord.attributes.tag.name'), with: 'whatever'
+ assert_difference 'Tag.count' do
+ click_on I18n.t('helpers.submit.create')
+ assert_text 'whatever'
+ end
+ end
+
+ test 'gives feedback on errors' do
+ visit new_tag_url
+
+ fill_in I18n.t('activerecord.attributes.tag.name'), with: tags(:tag1).name
+ click_on I18n.t('helpers.submit.create')
+ assert_text "#{I18n.t('activerecord.attributes.tag.name')} #{I18n.t('errors.messages.taken')}"
+ end
+
+ test 'can delete an existing tag' do
+ visit tags_url
+
+ assert_difference 'Tag.count', -1 do
+ click_link(I18n.t('general.delete'), match: :first)
+ assert_text I18n.t('tags.title')
+ end
+ end
+end
diff --git a/test/system/things_test.rb b/test/system/things_test.rb
new file mode 100644
index 0000000..9dd482d
--- /dev/null
+++ b/test/system/things_test.rb
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+require 'application_system_test_case'
+
+class ThingsTest < ApplicationSystemTestCase
+ setup { sign_in! }
+
+ test 'the hidden menu has a things#new link' do
+ find('#toggle-hidden-global-menu').click
+ assert_text I18n.t('things.object').downcase
+
+ click_on I18n.t('things.object').downcase
+ assert_text I18n.t('activerecord.attributes.thing.title')
+
+ assert page.current_path == new_thing_path
+ end
+
+ test 'you can click on a thing listed on the search to go to the its #show page' do
+ click_on things(:thing1).title
+
+ assert_text I18n.t('activerecord.attributes.thing.title')
+
+ assert page.current_path == edit_thing_path(things(:thing1))
+ end
+
+ test 'you can create a new thing' do
+ visit new_thing_url
+
+ fill_in I18n.t('activerecord.attributes.thing.title'), with: 'new title'
+ fill_in I18n.t('activerecord.attributes.thing.authors'), with: 'author'
+ fill_in I18n.t('activerecord.attributes.thing.target'), with: 'identifier'
+ fill_in I18n.t('activerecord.attributes.thing.rate'), with: 5
+ find("#thing_tag_ids_#{tags(:tag1).id}").click
+
+ click_on I18n.t('helpers.submit.create')
+
+ assert_text I18n.t('things.create-success')
+
+ # Ensure that tag references are properly created.
+ tags = Thing.find_by(title: 'new title').tags
+ assert tags.size == 1
+ assert tags.first.name == tags(:tag1).name
+
+ # You can go back to create another thing with a convenient link.
+ click_on I18n.t('things.create-another')
+ assert_text I18n.t('activerecord.attributes.thing.title')
+ assert page.current_path == new_thing_path
+ end
+
+ test 'you get feedback from wrong values for a new thing' do
+ visit new_thing_url
+
+ fill_in I18n.t('activerecord.attributes.thing.title'), with: things(:thing1).title
+ fill_in I18n.t('activerecord.attributes.thing.authors'), with: 'author'
+ fill_in I18n.t('activerecord.attributes.thing.target'), with: 'identifier'
+ fill_in I18n.t('activerecord.attributes.thing.rate'), with: 5
+ find("#thing_tag_ids_#{tags(:tag1).id}").click
+
+ click_on I18n.t('helpers.submit.create')
+
+ assert_text "#{I18n.t('activerecord.attributes.thing.title')} " \
+ "#{I18n.t('errors.messages.taken')}"
+ end
+
+ test 'you can update a value from a thing' do
+ visit edit_thing_url(things(:thing1))
+
+ # Originally :thing1 has references to :tag1 and :tag2. This test will
+ # remove the reference to :tag1.
+ assert things(:thing1).tag_references.size == 2
+
+ fill_in I18n.t('activerecord.attributes.thing.title'), with: 'another thing entirely'
+ find("#thing_tag_ids_#{tags(:tag1).id}").click
+ click_on I18n.t('helpers.submit.update')
+
+ assert_text I18n.t('things.update-success')
+
+ # Tag references updated: only one reference (:tag2).
+ tags = things(:thing1).reload.tags
+ assert tags.size == 1
+ assert tags.first.id = tags(:tag2).id
+ end
+
+ test 'you get feedback from wrong values for a thing' do
+ visit edit_thing_url(things(:thing1))
+
+ fill_in I18n.t('activerecord.attributes.thing.title'), with: things(:thing2).title
+ click_on I18n.t('helpers.submit.update')
+
+ assert_text "#{I18n.t('activerecord.attributes.thing.title')} " \
+ "#{I18n.t('errors.messages.taken')}"
+ end
+
+ test 'you can delete a thing' do
+ visit edit_thing_url(things(:thing1))
+
+ assert_difference 'Thing.count', -1 do
+ accept_alert { click_on I18n.t('general.delete').capitalize, match: :first }
+ assert_text I18n.t('things.destroy-success')
+ end
+ end
+end
diff --git a/test/test_helper.rb b/test/test_helper.rb
new file mode 100644
index 0000000..b13faef
--- /dev/null
+++ b/test/test_helper.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+ENV['RAILS_ENV'] ||= 'test'
+require_relative '../config/environment'
+require 'rails/test_help'
+
+# It helps when writing tests.
+require 'ap'
+
+module ActiveSupport
+ class TestCase
+ # Run tests in parallel with specified workers
+ parallelize(workers: :number_of_processors)
+
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
+ fixtures :all
+ end
+end