From 42a00f740b04555d9150f900145b4dd685000aaf Mon Sep 17 00:00:00 2001
From: Timothy Andrew <mail@timothyandrew.net>
Date: Mon, 25 Jul 2016 08:37:46 +0530
Subject: [PATCH] `WikiPage` should have a slug even when not persisted.

1. So we can build the markdown preview URL for it.

2. We can't skip the slug in this case, because the slug is used to
construct relative markdown URLs.

3. Add rspec feature tests to cover creating wiki pages with
   spaces/hyphens in the name.

4. Add rspec feature tests for markdown preview URL rewriting, which was
   only covered by unit tests up to this point.
---
 app/models/wiki_page.rb                       |   6 +-
 app/views/layouts/project.html.haml           |   2 +-
 .../projects/wiki/markdown_preview_spec.rb    | 140 ++++++++++++++++++
 .../wiki/user_creates_wiki_page_spec.rb       |  48 ++++--
 4 files changed, 185 insertions(+), 11 deletions(-)
 create mode 100644 spec/features/projects/wiki/markdown_preview_spec.rb

diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 3d5fd9d3ee9..c3de278f5b7 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -44,7 +44,11 @@ class WikiPage
 
   # The escaped URL path of this page.
   def slug
-    @attributes[:slug]
+    if @attributes[:slug].present?
+      @attributes[:slug]
+    else
+      wiki.wiki.preview_page(title, '', format).url_path
+    end
   end
 
   alias_method :to_param, :slug
diff --git a/app/views/layouts/project.html.haml b/app/views/layouts/project.html.haml
index 28cb6c56650..ee9c0366f2b 100644
--- a/app/views/layouts/project.html.haml
+++ b/app/views/layouts/project.html.haml
@@ -5,7 +5,7 @@
 
 - content_for :scripts_body_top do
   - project = @target_project || @project
-  - if @project_wiki && @page && @page.slug.present?
+  - if @project_wiki && @page
     - markdown_preview_path = namespace_project_wiki_markdown_preview_path(project.namespace, project, @page.slug)
   - else
     - markdown_preview_path = markdown_preview_namespace_project_path(project.namespace, project)
diff --git a/spec/features/projects/wiki/markdown_preview_spec.rb b/spec/features/projects/wiki/markdown_preview_spec.rb
new file mode 100644
index 00000000000..a1c386ddc18
--- /dev/null
+++ b/spec/features/projects/wiki/markdown_preview_spec.rb
@@ -0,0 +1,140 @@
+require 'spec_helper'
+
+feature 'Projects > Wiki > User previews markdown changes', feature: true, js: true do
+  let(:user) { create(:user) }
+  let(:project) { create(:project, namespace: user.namespace) }
+  let(:wiki_content) do
+    <<-HEREDOC
+[regular link](regular)
+[relative link 1](../relative)
+[relative link 2](./relative)
+[relative link 3](./e/f/relative)
+    HEREDOC
+  end
+
+  background do
+    project.team << [user, :master]
+    login_as(user)
+
+    visit namespace_project_path(project.namespace, project)
+    click_link 'Wiki'
+    WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
+  end
+
+  context "while creating a new wiki page" do
+    context "when there are no spaces or hyphens in the page name" do
+      it "rewrites relative links as expected" do
+        click_link 'New Page'
+        fill_in :new_wiki_path, with: 'a/b/c/d'
+        click_button 'Create Page'
+
+        fill_in :wiki_content, with: wiki_content
+        click_on "Preview"
+
+        expect(page).to have_content("regular link")
+
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/relative\">relative link 1</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/c/relative\">relative link 2</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/c/e/f/relative\">relative link 3</a>")
+      end
+    end
+
+    context "when there are spaces in the page name" do
+      it "rewrites relative links as expected" do
+        click_link 'New Page'
+        fill_in :new_wiki_path, with: 'a page/b page/c page/d page'
+        click_button 'Create Page'
+
+        fill_in :wiki_content, with: wiki_content
+        click_on "Preview"
+
+        expect(page).to have_content("regular link")
+
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/relative\">relative link 1</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>")
+      end
+    end
+
+    context "when there are hyphens in the page name" do
+      it "rewrites relative links as expected" do
+        click_link 'New Page'
+        fill_in :new_wiki_path, with: 'a-page/b-page/c-page/d-page'
+        click_button 'Create Page'
+
+        fill_in :wiki_content, with: wiki_content
+        click_on "Preview"
+
+        expect(page).to have_content("regular link")
+
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/relative\">relative link 1</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>")
+      end
+    end
+  end
+
+  context "while editing a wiki page" do
+    def create_wiki_page(path)
+      click_link 'New Page'
+      fill_in :new_wiki_path, with: path
+      click_button 'Create Page'
+      fill_in :wiki_content, with: 'content'
+      click_on "Create page"
+    end
+
+    context "when there are no spaces or hyphens in the page name" do
+      it "rewrites relative links as expected" do
+        create_wiki_page 'a/b/c/d'
+        click_link 'Edit'
+
+        fill_in :wiki_content, with: wiki_content
+        click_on "Preview"
+
+        expect(page).to have_content("regular link")
+
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/relative\">relative link 1</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/c/relative\">relative link 2</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a/b/c/e/f/relative\">relative link 3</a>")
+      end
+    end
+
+    context "when there are spaces in the page name" do
+      it "rewrites relative links as expected" do
+        create_wiki_page 'a page/b page/c page/d page'
+        click_link 'Edit'
+
+        fill_in :wiki_content, with: wiki_content
+        click_on "Preview"
+
+        expect(page).to have_content("regular link")
+
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/relative\">relative link 1</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>")
+      end
+    end
+
+    context "when there are hyphens in the page name" do
+      it "rewrites relative links as expected" do
+        create_wiki_page 'a-page/b-page/c-page/d-page'
+        click_link 'Edit'
+
+        fill_in :wiki_content, with: wiki_content
+        click_on "Preview"
+
+        expect(page).to have_content("regular link")
+
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/regular\">regular link</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/relative\">relative link 1</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/relative\">relative link 2</a>")
+        expect(page.html).to include("<a href=\"/#{project.path_with_namespace}/wikis/a-page/b-page/c-page/e/f/relative\">relative link 3</a>")
+      end
+    end
+  end
+end
diff --git a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
index 7e6eef65873..7afd83b7250 100644
--- a/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
+++ b/spec/features/projects/wiki/user_creates_wiki_page_spec.rb
@@ -30,18 +30,48 @@ feature 'Projects > Wiki > User creates wiki page', feature: true do
         WikiPages::CreateService.new(project, user, title: 'home', content: 'Home page').execute
       end
 
-      scenario 'via the "new wiki page" page', js: true do
-        click_link 'New Page'
+      context 'via the "new wiki page" page' do
+        scenario 'when the wiki page has a single word name', js: true do
+          click_link 'New Page'
 
-        fill_in :new_wiki_path, with: 'foo'
-        click_button 'Create Page'
+          fill_in :new_wiki_path, with: 'foo'
+          click_button 'Create Page'
 
-        fill_in :wiki_content, with: 'My awesome wiki!'
-        click_button 'Create page'
+          fill_in :wiki_content, with: 'My awesome wiki!'
+          click_button 'Create page'
 
-        expect(page).to have_content('Foo')
-        expect(page).to have_content("last edited by #{user.name}")
-        expect(page).to have_content('My awesome wiki!')
+          expect(page).to have_content('Foo')
+          expect(page).to have_content("last edited by #{user.name}")
+          expect(page).to have_content('My awesome wiki!')
+        end
+
+        scenario 'when the wiki page has spaces in the name', js: true do
+          click_link 'New Page'
+
+          fill_in :new_wiki_path, with: 'Spaces in the name'
+          click_button 'Create Page'
+
+          fill_in :wiki_content, with: 'My awesome wiki!'
+          click_button 'Create page'
+
+          expect(page).to have_content('Spaces in the name')
+          expect(page).to have_content("last edited by #{user.name}")
+          expect(page).to have_content('My awesome wiki!')
+        end
+
+        scenario 'when the wiki page has hyphens in the name', js: true do
+          click_link 'New Page'
+
+          fill_in :new_wiki_path, with: 'hyphens-in-the-name'
+          click_button 'Create Page'
+
+          fill_in :wiki_content, with: 'My awesome wiki!'
+          click_button 'Create page'
+
+          expect(page).to have_content('Hyphens in the name')
+          expect(page).to have_content("last edited by #{user.name}")
+          expect(page).to have_content('My awesome wiki!')
+        end
       end
     end
   end
-- 
GitLab