diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb index 7db232e3dfc51eefdbdfd7f7ae4e962795a110a8..da6f04b0020ef37e3048ae2c01ecef66a3930c89 100644 --- a/test/application_system_test_case.rb +++ b/test/application_system_test_case.rb @@ -62,4 +62,42 @@ class ApplicationSystemTestCase < ActionDispatch::SystemTestCase users(user_or_fixture) end end + + # In the post form, this method will select the given tag. + # + # @param tag_name [String] the name of the tag + # @param create_new [Boolean] whether creating a new tag is allowed (default false) + def post_form_select_tag(tag_name, create_new = false) + # First enter the tag name into the select2 search field for the tag + within find_field('Tags (at least one):').find(:xpath, '..') do + find('.select2-search__field').fill_in(with: tag_name) + end + + # Get the first item listed that is not the "Searching..." item + first_option = find('#select2-post_tags_cache-results li:first-child') { |el| el.text != 'Searching…' } + + if first_option.first('span').text == tag_name + # If the text matches the tag name, first check whether we are creating a new tag. + # If so, confirm that we are allowed to. If all is good, actually click on the item. + if create_new || !first_option.text.include?('Create new tag') + first_option.click + else + raise "Expected to find tag with the name #{tag_name}, " \ + 'but could not select it from options without creating a new tag.' + end + elsif create_new + # The first item returned is not the tag we were looking for (another tag partial match + not existing) + # If we are allowed to create a tag, select the last option from the list, which is always the tag creation. + last_option = find('#select2-post_tags_cache-results li:last-child') + if last_option.first('span').text == tag_name + last_option.click + else + raise "Tried to select tag #{tag_name} for creation, but it does not seem to be a presented option." + end + else + # The first item returned is not the tag we were looking for, and we are not allowed to create a tag. + raise "Expected to find tag with the name #{tag_name}, " \ + 'but could not select it from options without creating a new tag.' + end + end end diff --git a/test/fixtures/posts.yml b/test/fixtures/posts.yml index afbab5147a4926a388b3406737a43789e49e51fd..e67b996fbea5935fa33cf500ba23f124515d3572 100644 --- a/test/fixtures/posts.yml +++ b/test/fixtures/posts.yml @@ -1,8 +1,8 @@ question_one: post_type: question - title: Q1 ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + title: Q1 - This is test question number one + body: This is the body of test question one. Note that we did not include any markdown or HTML in here. + body_markdown: This is the body of test question one. Note that we did not include any markdown or HTML in here. tags_cache: - discussion - support @@ -21,9 +21,9 @@ question_one: question_two: post_type: question - title: Q2 ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + title: Q2 - This is test question number two + body: This is the body of test question two. Note that we did not include any markdown or HTML in here. + body_markdown: This is the body of test question two. Note that we did not include any markdown or HTML in here. tags_cache: - discussion - support @@ -42,9 +42,9 @@ question_two: bad_answers: post_type: question - title: Q1 ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + title: Q3B - This question has bad answers + body: Q3B - This question is in the category main, posted by standard_user. It has bad answers. + body_markdown: Q3B - This question is in the category main, posted by standard_user. It has bad answers. tags_cache: - discussion - support @@ -63,9 +63,9 @@ bad_answers: deleted: post_type: question - title: Q3D ZY XWVUTS RQPONM LKJIHG FEDCBA - body: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + title: Q3D - This question is deleted + body: Q3D - This question is in the category main, posted by standard_user. It has been deleted by deleter. + body_markdown: Q3D - This question is in the category main, posted by standard_user. It has been deleted by deleter. tags_cache: - discussion - support @@ -87,9 +87,9 @@ deleted: deleted_mod: post_type: question - title: Q3D ZY XWVUTS RQPONM LKJIHG FEDCBA - body: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + title: Q3DM - This question is deleted by a moderator + body: Q3DM - This question is in category main, posted by standard_user. It has been deleted by moderator. + body_markdown: Q3DM - This question is in category main, posted by standard_user. It has been deleted by moderator. tags_cache: - discussion - support @@ -111,9 +111,9 @@ deleted_mod: closed: post_type: question - title: Q4C ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + title: Q4C - This question is closed + body: Q4C - This question is in the category main, posted by standard_user. It has been closed by closer. + body_markdown: Q4C - This question is in the category main, posted by standard_user. It has been closed by closer. tags_cache: - discussion - support @@ -135,9 +135,9 @@ closed: locked: post_type: question - title: Q4C ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + title: Q4L - This question is locked + body: Q4L - This question is in the category main, posted by standard_user. It has been locked by deleter. + body_markdown: Q4L - This question is in the category main, posted by standard_user. It has been locked by deleter. tags_cache: - discussion - support @@ -160,9 +160,9 @@ locked: locked_mod: post_type: question - title: LM ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + title: Q4LM - This question is locked by a moderator + body: Q4LM - This question is in the category main, posted by standard_user. It has been locked by moderator. + body_markdown: Q4LM - This question is in the category main, posted by standard_user. It has been locked by moderator. tags_cache: - discussion - support @@ -185,9 +185,9 @@ locked_mod: free_edit: post_type: free_edit - title: FE ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + title: FE - This is a post of the type free_edit + body: FE - This is a free edit post, in the category main, posted by moderator. + body_markdown: FE - This is a free edit post, in the category main, posted by moderator. tags_cache: - discussion - support @@ -206,9 +206,9 @@ free_edit: high_trust: post_type: question - title: Q1 ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + title: Q5 - This is a question with high trust + body: Q5 - By not providing any information, you know you can trust everything said in this post. + body_markdown: Q5 - By not providing any information, you know you can trust everything said in this post. tags_cache: - discussion - support @@ -227,9 +227,8 @@ high_trust: answer_one: post_type: answer - title: A1 ABCDEF GHIJKL MNOPQR - body: A1 ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + body: A1 - This is the first answer to question number 1 (Q1). It was posted by standard user. + body_markdown: A1 - This is the first answer to question number 1 (Q1). It was posted by standard user. score: 0.5 parent: question_one user: standard_user @@ -241,9 +240,8 @@ answer_one: answer_two: post_type: answer - title: A2 ABCDEF GHIJKL MNOPQR - body: A2 ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + body: A2 - This is the second answer to question number 1 (Q1). It was posted by editor. + body_markdown: A2 - This is the second answer to question number 1 (Q1). It was posted by editor. score: 0.5 parent: question_one user: editor @@ -255,9 +253,8 @@ answer_two: comments_disabled: post_type: answer - title: A2 ABCDEF GHIJKL MNOPQR - body: A2 ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + body: A3CD - This is the third answer to question number 1 (Q1). It has comments disabled. Posted by closer. + body_markdown: A3 - This is the third answer to question number 1 (Q1). It has comments disabled. Posted by closer. score: 0.5 parent: question_one user: closer @@ -270,9 +267,8 @@ comments_disabled: bad_answer: post_type: answer - title: A2 ABCDEF GHIJKL MNOPQR - body: A2 ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + body: A3BA - This is the fourth answer to question number 1 (Q1). It has a bad score. Posted by editor. + body_markdown: A4 - This is the fourth answer to question number 1 (Q1). It has a bad score. Posted by editor. score: 0.4 parent: question_one user: editor @@ -284,9 +280,8 @@ bad_answer: really_old_answer: post_type: answer - title: A3RO ABCDEF GHIJKL MNOPQR - body: A3RO ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + body: A3RO - This is the fifth answer to question number 1 (Q1). It is very old. Posted by standard_user. + body_markdown: A3RO - This is the fifth answer to question number 1 (Q1). It is very old. Posted by standard_user. score: 2 parent: question_one user: standard_user @@ -299,9 +294,8 @@ really_old_answer: deleted_answer: post_type: answer - title: A4D ABCDEF GHIJKL MNOPQR - body: A4D ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + body: A4D - This is the sixth answer to question number 1 (Q1). It is deleted. Posted by closer. + body_markdown: A4D - This is the sixth answer to question number 1 (Q1). It is deleted. Posted by closer. score: 0.5 parent: question_one user: closer @@ -316,8 +310,8 @@ deleted_answer: policy_doc: post_type: policy_doc - body: PD ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ZY XWVUTS RQPONM LKJIHG FEDCBA ZY XWVUTS RQPONM LKJIHG FEDCBA + body: PD - This is a policy document called "Terms of Service", or "tos" for short. + body_markdown: PD - This is a policy document called "Terms of Service", or "tos" for short. title: Terms of Service doc_slug: tos user: admin @@ -336,9 +330,9 @@ help_doc: article_one: post_type: article - title: Q1 ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + title: Art1 - This is the first article + body: Testing is an important practice, which should probably be discussed in this test article. + body_markdown: Testing is an important practice, which should probably be discussed in this test article. tags_cache: - discussion - support @@ -357,9 +351,9 @@ article_one: deleted_article: post_type: article - title: Q1 ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + title: Art2D - This is a deleted article + body: Articles are most likely deleted because they have no inherent value, just like this sentence. + body_markdown: Articles are most likely deleted because they have no inherent value, just like this sentence. tags_cache: - discussion - support @@ -381,8 +375,8 @@ deleted_article: help_article: post_type: help_doc - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + body: HA1 - This help article is in the category Site information, with "sample" as slug. + body_markdown: HA1 - This help article is in the category Site information, with "sample" as slug. user: system community: sample help_category: Site Information @@ -391,8 +385,8 @@ help_article: mod_help_article: post_type: help_doc - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + body: HA2 - This help article is in the category for moderators only, with "sample-mod" as slug. + body_markdown: HA2 - This help article is in the category for moderators only, with "sample-mod" as slug. user: system community: sample help_category: $Moderator @@ -401,8 +395,8 @@ mod_help_article: disabled_help_article: post_type: help_doc - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + body: HA3 - This help article is disabled. It is in the category disabled, with "sample-disable" as slug. + body_markdown: HA3 - This help article is disabled. It is in the category disabled, with "sample-disable" as slug. user: system community: sample help_category: $Disabled @@ -411,9 +405,9 @@ disabled_help_article: blog_post: post_type: blog_post - title: B1 ABCDEF GHIJKL MNOPQR STUVWX YZ - body: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ - body_markdown: ABCDEF GHIJKL MNOPQR STUVWX YZ ABCDEF GHIJKL MNOPQR STUVWX YZ + title: B1 - This is a blog post in the main category + body: B1 - This blog post is in the main category, posted by closer. + body_markdown: B1 - This blog post is in the main category, posted by closer. tags_cache: - discussion - support diff --git a/test/system/post_test.rb b/test/system/post_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..d99cd266cab58145a3a2c59942ef050ee184fa33 --- /dev/null +++ b/test/system/post_test.rb @@ -0,0 +1,166 @@ +require 'application_system_test_case' + +class PostTest < ApplicationSystemTestCase + # ------------------------------------------------------- + # Create + # ------------------------------------------------------- + + test 'Not-signed in user cannot create a post' do + visit root_url + click_on 'Create Post' + + assert_current_path new_user_session_url + end + + test 'Signed in user can create a question' do + category = categories(:meta) + log_in :standard_user + visit category_path(category) + click_on 'Create Post' + + body_text = 'When running QPixel, users are generally supposed to be able to create posts. ' \ + 'Does that actually work?' + title_text = 'Can a signed-in user create a post?' + + fill_in 'Body', with: body_text + fill_in 'Summarize your post with a title:', with: title_text + post_form_select_tag tags(:faq).name + + # Check that the post is actually created + assert_difference 'Post.count' do + click_on "Save Post in #{category.name}" + end + + # Verify that the post is correctly created + new_post = Post.last + assert_equal body_text, new_post.body_markdown + assert_equal title_text, new_post.title + assert_equal [tags(:faq)], new_post.tags + end + + test 'Creating a question is blocked when body is too short' do + category = categories(:meta) + log_in :standard_user + visit category_path(category) + click_on 'Create Post' + + fill_in 'Summarize your post with a title:', with: 'Initial title is of sufficient length' + post_form_select_tag tags(:faq).name + fill_in 'Body', with: 'Short' + + # Check that the button is disabled + find_button "Save Post in #{category.name}", disabled: true + + # After filling out body correctly, verify that the button becomes enabled + fill_in 'Body', with: 'This body should pass the minimum length requirements for questions in the meta category.' + find_button "Save Post in #{category.name}", disabled: false + end + + test 'Creating a question is blocked when title is too short' do + category = categories(:meta) + log_in :standard_user + visit category_path(category) + click_on 'Create Post' + + fill_in 'Body', with: 'This body should pass the minimum length requirements for questions in the meta category.' + post_form_select_tag tags(:faq).name + fill_in 'Summarize your post with a title:', with: 'Too short' + + # Check that the button is disabled + find_button "Save Post in #{category.name}", disabled: true + + # After filling out the title, verify that the button becomes enabled + fill_in 'Summarize your post with a title:', with: 'Updated title is of sufficient length' + find_button "Save Post in #{category.name}", disabled: false + end + + test 'Signed in user gets to pick post type for post creation in categories with multiple types' do + category = categories(:main) + log_in :standard_user + visit category_path(category) + click_on 'Create Post' + + # All the top level post types set should be present + category.post_types.where(is_top_level: true).each do |pt| + assert_link pt.name.underscore.humanize + end + + # Pick a non-question post type + post_type = category.post_types.where(is_top_level: true).where.not(name: 'Question').first + + # After clicking on a post type, we should be on the creation page of the correct category and post type. + click_on post_type.name.underscore.humanize + assert_current_path new_category_post_url(post_type.id, category.id) + end + + test 'Signed in user can answer question' do + log_in :standard_user + post = posts(:question_two) + visit post_path(post) + + # Answer the question + answer_text = 'You can do this by running the rails system tests, rails test:system.' + fill_in 'Body', with: answer_text + assert_difference 'Post.count' do + click_on "Save Post in #{post.category.name}" + end + + # We should now be looking at our answer, look for the text on the page + assert_text answer_text + + # The original post should also still be on the page + assert_text post.body + end + + # ------------------------------------------------------- + # Show + # ------------------------------------------------------- + + test 'Anyone can view question' do + post = posts(:question_one) + visit post_url(post) + + # Check that the post is displayed somewhere on the page + assert_text post.title + assert_text post.body + + # Check that answers are displayed somewhere on the page + assert post.children.any?, 'The post for this system test should have answers' + post.children.where(deleted: false).each do |child| + assert_text child.body + end + end + + test 'Anyone can sort answers' do + post = posts(:question_one) + visit post_url(post) + + click_on 'Active' + + assert_current_path post_url(post, sort: 'active') + end + + # ------------------------------------------------------- + # Edit + # ------------------------------------------------------- + + test 'User with edit permissions can directly edit question' do + log_in :editor + post = posts(:question_two) + visit post_url(post) + + within ".post[data-post-id=\"#{post.id}\"]" do + click_on 'Edit' + end + + updated_text = 'This is the updated body text, which should be quite different from the original text!' + fill_in 'Body', with: updated_text + fill_in 'Edit Comment', with: 'Major Rewrite for Tests' + + click_on "Save Post in #{post.category.name}" + assert_current_path post_url(post) + + # Check that the page shows the updated text + assert_text updated_text + end +end