From f25344e36e9c1b0d0df2211b82b26c6515e96c31 Mon Sep 17 00:00:00 2001
From: Alex Braha Stoll <alexbrahastoll@gmail.com>
Date: Mon, 19 Dec 2016 02:34:35 -0200
Subject: [PATCH] Change WikiPage.group_by_directory to order by directory and
 file alphabetical order

---
 app/models/wiki_page.rb       | 29 ++++++++++++++++++++++++++++-
 spec/models/wiki_page_spec.rb | 30 ++++++++++++++++++++++++++----
 2 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index a563b0b7a72..a84f84c67cd 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -12,10 +12,17 @@ class WikiPage
     ActiveModel::Name.new(self, nil, 'wiki')
   end
 
+  # Sorts and groups pages by directory.
+  #
+  # pages - an array of WikiPage objects.
+  #
+  # Returns a hash whose keys are directories and whose values are WikiPage
+  # arrays. See WikiPage.sort_by_directory for more info about the ordering.
   def self.group_by_directory(pages)
     return {} if pages.blank?
-    directories = { '/' => [] }
+    pages = sort_by_directory(pages)
 
+    directories = {}
     pages.each do |page|
       directories[page.directory] ||= []
       directories[page.directory] << page
@@ -199,6 +206,26 @@ class WikiPage
 
   private
 
+  # Sorts an array of pages by directory and file alphabetical order.
+  # Pages at the root directory will come first. The next pages will be
+  # sorted by their directories. Within directories, pages are sorted by
+  # filename alphabetical order. Pages are sorted in such a fashion that
+  # nested directories will always follow their parents (e.g. pages in
+  # dir_1/nested_dir_1 will follow pages inside dir_1).
+  #
+  # pages - an array of WikiPage objects.
+  #
+  # Returns a sorted array of WikiPage objects.
+  def self.sort_by_directory(pages)
+    pages.sort do |page, next_page|
+      if page.directory == next_page.directory
+        page.slug <=> next_page.slug
+      else
+        page.directory <=> next_page.directory
+      end
+    end
+  end
+
   def set_attributes
     attributes[:slug] = @page.url_path
     attributes[:title] = @page.title
diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb
index 91d5fccce60..374849e1932 100644
--- a/spec/models/wiki_page_spec.rb
+++ b/spec/models/wiki_page_spec.rb
@@ -17,17 +17,22 @@ describe WikiPage, models: true do
 
     context 'when there are pages' do
       before do
-        create_page('page_1', 'content')
+        create_page('dir_1/dir_1_1/page_3', 'content')
         create_page('dir_1/page_2', 'content')
-        create_page('dir_1/dir_2/page_3', 'content')
+        create_page('dir_2/page_5', 'content')
+        create_page('dir_2/page_4', 'content')
+        create_page('page_1', 'content')
       end
 
       it 'returns a hash in which keys are directories and values are their pages' do
         page_1 = wiki.find_page('page_1')
         page_2 = wiki.find_page('dir_1/page_2')
-        page_3 = wiki.find_page('dir_1/dir_2/page_3')
+        page_3 = wiki.find_page('dir_1/dir_1_1/page_3')
+        page_4 = wiki.find_page('dir_2/page_4')
+        page_5 = wiki.find_page('dir_2/page_5')
         expected_grouped_pages = {
-          '/' => [page_1], '/dir_1' => [page_2], '/dir_1/dir_2' => [page_3]
+          '/' => [page_1], '/dir_1' => [page_2], '/dir_1/dir_1_1' => [page_3],
+          '/dir_2' => [page_4, page_5]
         }
 
         grouped_pages = WikiPage.group_by_directory(wiki.pages)
@@ -39,6 +44,23 @@ describe WikiPage, models: true do
           expect(slugs).to match_array(expected_slugs)
         end
       end
+
+      it 'returns a hash in which keys (directories) are sorted by alphabetical position' do
+        expected_ordered_directories = ['/', '/dir_1', '/dir_1/dir_1_1', '/dir_2']
+
+        grouped_pages = WikiPage.group_by_directory(wiki.pages)
+
+        expect(grouped_pages.keys).to eq(expected_ordered_directories)
+      end
+
+      it 'returns a hash in which values (pages) are sorted by alphabetical position' do
+        expected_ordered_page_slugs = ['dir_2/page_4', 'dir_2/page_5']
+
+        grouped_pages = WikiPage.group_by_directory(wiki.pages)
+
+        dir_2_page_slugs = grouped_pages.fetch('/dir_2').map(&:slug)
+        expect(dir_2_page_slugs).to eq(expected_ordered_page_slugs)
+      end
     end
   end
 
-- 
GitLab