gitlab-org--gitlab-foss/spec/models/wiki_directory_spec.rb

232 lines
6.8 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
require 'set'
RSpec.describe WikiDirectory do
include GitHelpers
let(:project) { create(:project, :wiki_repo) }
let(:user) { project.owner }
let(:wiki) { ProjectWiki.new(project, user) }
describe 'validations' do
subject { build(:wiki_directory) }
it { is_expected.to validate_presence_of(:slug) }
end
describe '.group_by_directory' do
context 'when there are no pages' do
it 'returns an empty array' do
expect(described_class.group_by_directory(nil)).to eq([])
expect(described_class.group_by_directory([])).to eq([])
end
end
context 'when there are pages' do
before do
create_page('dir_1/dir_1_1/page_3', 'content')
create_page('page_1', 'content')
create_page('dir_1/page_2', 'content')
create_page('dir_2', 'page with dir name')
create_page('dir_2/page_5', 'content')
create_page('page_6', 'content')
create_page('dir_2/page_4', 'content')
end
let(:page_1) { wiki.find_page('page_1') }
let(:page_6) { wiki.find_page('page_6') }
let(:page_dir_2) { wiki.find_page('dir_2') }
let(:dir_1) do
described_class.new('dir_1', [wiki.find_page('dir_1/page_2')])
end
let(:dir_1_1) do
described_class.new('dir_1/dir_1_1', [wiki.find_page('dir_1/dir_1_1/page_3')])
end
let(:dir_2) do
pages = [wiki.find_page('dir_2/page_5'),
wiki.find_page('dir_2/page_4')]
described_class.new('dir_2', pages)
end
context "#list_pages" do
shared_examples "a correct grouping" do
let(:grouped_slugs) { grouped_entries.map(&method(:slugs)) }
let(:expected_slugs) { expected_grouped_entries.map(&method(:slugs)).map(&method(:match_array)) }
it 'returns an array with pages and directories' do
expect(grouped_slugs).to match_array(expected_slugs)
end
end
context 'sort by title' do
let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages) }
let(:expected_grouped_entries) { [dir_1_1, dir_1, page_dir_2, dir_2, page_1, page_6] }
it_behaves_like "a correct grouping"
end
context 'sort by created_at' do
let(:grouped_entries) { described_class.group_by_directory(wiki.list_pages(sort: 'created_at')) }
let(:expected_grouped_entries) { [dir_1_1, page_1, dir_1, page_dir_2, dir_2, page_6] }
it_behaves_like "a correct grouping"
end
it 'returns an array with retained order with directories at the top' do
expected_order = ['dir_1/dir_1_1/page_3', 'dir_1/page_2', 'dir_2', 'dir_2/page_4', 'dir_2/page_5', 'page_1', 'page_6']
grouped_entries = described_class.group_by_directory(wiki.list_pages)
actual_order = grouped_entries.flat_map(&method(:slugs))
expect(actual_order).to eq(expected_order)
end
end
end
end
describe '#initialize' do
context 'when there are pages' do
let(:pages) { [build(:wiki_page)] }
let(:directory) { described_class.new('/path_up_to/dir', pages) }
it 'sets the slug attribute' do
expect(directory.slug).to eq('/path_up_to/dir')
end
it 'sets the pages attribute' do
expect(directory.pages).to eq(pages)
end
end
context 'when there are no pages' do
let(:directory) { described_class.new('/path_up_to/dir') }
it 'sets the slug attribute' do
expect(directory.slug).to eq('/path_up_to/dir')
end
it 'sets the pages attribute to an empty array' do
expect(directory.pages).to eq([])
end
end
end
describe '#to_partial_path' do
it 'returns the relative path to the partial to be used' do
directory = build(:wiki_directory)
expect(directory.to_partial_path).to eq('projects/wiki_directories/wiki_directory')
end
end
describe 'attributes' do
def page_path(index)
"dir-path/page-#{index}"
end
let(:page_paths) { (1..3).map { |n| page_path(n) } }
let(:pages) do
page_paths.map { |p| wiki.find_page(p) }
end
subject { described_class.new('dir-path', pages) }
context 'there are no pages' do
let(:pages) { [] }
it { is_expected.to have_attributes(page_count: 0, last_version: be_nil) }
end
context 'there is one page' do
before do
create_page("dir-path/singleton", "Just this page")
end
let(:the_page) { wiki.find_page("dir-path/singleton") }
let(:pages) { [the_page] }
it { is_expected.to have_attributes(page_count: 1, last_version: the_page.last_version) }
end
context 'there are a few pages, each with a single version' do
before do
page_paths.each_with_index do |path, n|
Timecop.freeze(Time.local(1990) + n.minutes) do
create_page(path, "this is page #{n}")
end
end
end
let(:expected_last_version) { pages.last.last_version }
it { is_expected.to have_attributes(page_count: 3, last_version: expected_last_version) }
end
context 'there are a few pages, each with a few versions' do
before do
page_paths.each_with_index do |path, n|
t = Time.local(1990) + n.minutes
Timecop.freeze(t) do
create_page(path, "This is page #{n}")
(2..3).each do |v|
Timecop.freeze(t + v.seconds) do
update_page(path, "Now at version #{v}")
end
end
end
end
end
it { is_expected.to have_attributes(page_count: 3, last_version: pages.last.last_version) }
end
end
private
def create_page(name, content)
wiki.wiki.write_page(name, :markdown, content, commit_details)
set_time(name)
end
def update_page(name, content)
wiki.wiki.update_page(name, name, :markdown, content, update_commit_details)
set_time(name)
end
def set_time(name)
return unless Timecop.frozen?
new_date = Time.now
page = wiki.find_page(name).page
commit = page.version.commit
repo = commit.instance_variable_get(:@repository)
rug_commit = rugged_repo_at_path(repo.relative_path).lookup(commit.id)
rug_commit.amend(
message: rug_commit.message,
tree: rug_commit.tree,
author: rug_commit.author.merge(time: new_date),
committer: rug_commit.committer.merge(time: new_date),
update_ref: 'HEAD'
)
end
def commit_details
Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "test commit")
end
def update_commit_details
Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "test update")
end
def slugs(thing)
Array.wrap(thing.respond_to?(:pages) ? thing.pages.map(&:slug) : thing.slug)
end
end