diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-15 03:09:11 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-04-15 03:09:11 +0000 |
commit | b71a496c7a3e109f7c85ad7ac453e6f7bf7cda45 (patch) | |
tree | 0a76fc00ef860bd369dcaa3f136ee36275eb47f5 /spec/models | |
parent | c2041156b8b3063d6cf29b324416e8469e588923 (diff) | |
download | gitlab-ce-b71a496c7a3e109f7c85ad7ac453e6f7bf7cda45.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/models')
-rw-r--r-- | spec/models/active_session_spec.rb | 48 | ||||
-rw-r--r-- | spec/models/wiki_page_spec.rb | 202 |
2 files changed, 224 insertions, 26 deletions
diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb index 27a80f93566..6a97d91b3ca 100644 --- a/spec/models/active_session_spec.rb +++ b/spec/models/active_session_spec.rb @@ -9,10 +9,8 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do end end - let(:session) do - double(:session, { id: '6919a6f1bb119dd7396fadc38fd18d0d', - '[]': {} }) - end + let(:rack_session) { Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d') } + let(:session) { instance_double(ActionDispatch::Request::Session, id: rack_session, '[]': {}) } let(:request) do double(:request, { @@ -25,13 +23,13 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do describe '#current?' do it 'returns true if the active session matches the current session' do - active_session = ActiveSession.new(session_id: '6919a6f1bb119dd7396fadc38fd18d0d') + active_session = ActiveSession.new(session_id: rack_session) expect(active_session.current?(session)).to be true end it 'returns false if the active session does not match the current session' do - active_session = ActiveSession.new(session_id: '59822c7d9fcdfa03725eff41782ad97d') + active_session = ActiveSession.new(session_id: Rack::Session::SessionId.new('59822c7d9fcdfa03725eff41782ad97d')) expect(active_session.current?(session)).to be false end @@ -46,14 +44,12 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do describe '#public_id' do it 'returns an encrypted, url-encoded session id' do - original_session_id = "!*'();:@&\n=+$,/?%abcd#123[4567]8" + original_session_id = Rack::Session::SessionId.new("!*'();:@&\n=+$,/?%abcd#123[4567]8") active_session = ActiveSession.new(session_id: original_session_id) - encrypted_encoded_id = active_session.public_id - - encrypted_id = CGI.unescape(encrypted_encoded_id) + encrypted_id = active_session.public_id derived_session_id = Gitlab::CryptoHelper.aes256_gcm_decrypt(encrypted_id) - expect(original_session_id).to eq derived_session_id + expect(original_session_id.public_id).to eq derived_session_id end end @@ -104,7 +100,8 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do describe '.list_sessions' do it 'uses the ActiveSession lookup to return original sessions' do Gitlab::Redis::SharedState.with do |redis| - redis.set("session:gitlab:6919a6f1bb119dd7396fadc38fd18d0d", Marshal.dump({ _csrf_token: 'abcd' })) + # Emulate redis-rack: https://github.com/redis-store/redis-rack/blob/c75f7f1a6016ee224e2615017fbfee964f23a837/lib/rack/session/redis.rb#L88 + redis.set("session:gitlab:#{rack_session.private_id}", Marshal.dump({ _csrf_token: 'abcd' })) redis.sadd( "session:lookup:user:gitlab:#{user.id}", @@ -127,17 +124,18 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do redis.sadd("session:lookup:user:gitlab:#{user.id}", session_ids) end - expect(ActiveSession.session_ids_for_user(user.id)).to eq(session_ids) + expect(ActiveSession.session_ids_for_user(user.id).map(&:to_s)).to eq(session_ids) end end describe '.sessions_from_ids' do it 'uses the ActiveSession lookup to return original sessions' do Gitlab::Redis::SharedState.with do |redis| - redis.set("session:gitlab:6919a6f1bb119dd7396fadc38fd18d0d", Marshal.dump({ _csrf_token: 'abcd' })) + # Emulate redis-rack: https://github.com/redis-store/redis-rack/blob/c75f7f1a6016ee224e2615017fbfee964f23a837/lib/rack/session/redis.rb#L88 + redis.set("session:gitlab:#{rack_session.private_id}", Marshal.dump({ _csrf_token: 'abcd' })) end - expect(ActiveSession.sessions_from_ids(['6919a6f1bb119dd7396fadc38fd18d0d'])).to eq [{ _csrf_token: 'abcd' }] + expect(ActiveSession.sessions_from_ids([rack_session])).to eq [{ _csrf_token: 'abcd' }] end it 'avoids a redis lookup for an empty array' do @@ -152,11 +150,12 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do redis = double(:redis) expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis) - sessions = %w[session-a session-b] + sessions = %w[session-a session-b session-c session-d] mget_responses = sessions.map { |session| [Marshal.dump(session)]} - expect(redis).to receive(:mget).twice.and_return(*mget_responses) + expect(redis).to receive(:mget).exactly(4).times.and_return(*mget_responses) - expect(ActiveSession.sessions_from_ids([1, 2])).to eql(sessions) + session_ids = [1, 2].map { |id| Rack::Session::SessionId.new(id.to_s) } + expect(ActiveSession.sessions_from_ids(session_ids).map(&:to_s)).to eql(sessions) end end @@ -212,6 +211,12 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do end describe '.destroy' do + it 'gracefully handles a nil session ID' do + expect(described_class).not_to receive(:destroy_sessions) + + ActiveSession.destroy(user, nil) + end + it 'removes the entry associated with the currently killed user session' do Gitlab::Redis::SharedState.with do |redis| redis.set("session:user:gitlab:#{user.id}:6919a6f1bb119dd7396fadc38fd18d0d", '') @@ -244,8 +249,9 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do it 'removes the devise session' do Gitlab::Redis::SharedState.with do |redis| - redis.set("session:user:gitlab:#{user.id}:6919a6f1bb119dd7396fadc38fd18d0d", '') - redis.set("session:gitlab:6919a6f1bb119dd7396fadc38fd18d0d", '') + redis.set("session:user:gitlab:#{user.id}:#{rack_session.public_id}", '') + # Emulate redis-rack: https://github.com/redis-store/redis-rack/blob/c75f7f1a6016ee224e2615017fbfee964f23a837/lib/rack/session/redis.rb#L88 + redis.set("session:gitlab:#{rack_session.private_id}", '') end ActiveSession.destroy(user, request.session.id) @@ -322,7 +328,7 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do (1..max_number_of_sessions_plus_two).each do |number| redis.set( "session:user:gitlab:#{user.id}:#{number}", - Marshal.dump(ActiveSession.new(session_id: "#{number}", updated_at: number.days.ago)) + Marshal.dump(ActiveSession.new(session_id: number.to_s, updated_at: number.days.ago)) ) redis.sadd( "session:lookup:user:gitlab:#{user.id}", diff --git a/spec/models/wiki_page_spec.rb b/spec/models/wiki_page_spec.rb index 0a0611bdeb8..718b386b3fd 100644 --- a/spec/models/wiki_page_spec.rb +++ b/spec/models/wiki_page_spec.rb @@ -20,6 +20,17 @@ describe WikiPage do subject { new_page } + def disable_front_matter + stub_feature_flags(Gitlab::WikiPages::FrontMatterParser::FEATURE_FLAG => false) + end + + def enable_front_matter_for_project + stub_feature_flags(Gitlab::WikiPages::FrontMatterParser::FEATURE_FLAG => { + thing: project, + enabled: true + }) + end + describe '.group_by_directory' do context 'when there are no pages' do it 'returns an empty array' do @@ -101,6 +112,119 @@ describe WikiPage do end end + describe '#front_matter' do + let_it_be(:project) { create(:project) } + let(:wiki_page) { create(:wiki_page, project: project, content: content) } + + shared_examples 'a page without front-matter' do + it { expect(wiki_page).to have_attributes(front_matter: {}, content: content) } + end + + shared_examples 'a page with front-matter' do + let(:front_matter) { { title: 'Foo', slugs: %w[slug_a slug_b] } } + + it { expect(wiki_page.front_matter).to eq(front_matter) } + end + + context 'the wiki page has front matter' do + let(:content) do + <<~MD + --- + title: Foo + slugs: + - slug_a + - slug_b + --- + + My actual content + MD + end + + it_behaves_like 'a page with front-matter' + + it 'strips the front matter from the content' do + expect(wiki_page.content.strip).to eq('My actual content') + end + + context 'the feature flag is off' do + before do + disable_front_matter + end + + it_behaves_like 'a page without front-matter' + + context 'but enabled for the project' do + before do + enable_front_matter_for_project + end + + it_behaves_like 'a page with front-matter' + end + end + end + + context 'the wiki page does not have front matter' do + let(:content) { 'My actual content' } + + it_behaves_like 'a page without front-matter' + end + + context 'the wiki page has fenced blocks, but nothing in them' do + let(:content) do + <<~MD + --- + --- + + My actual content + MD + end + + it_behaves_like 'a page without front-matter' + end + + context 'the wiki page has invalid YAML type in fenced blocks' do + let(:content) do + <<~MD + --- + this isn't YAML + --- + + My actual content + MD + end + + it_behaves_like 'a page without front-matter' + end + + context 'the wiki page has a disallowed class in fenced block' do + let(:content) do + <<~MD + --- + date: 2010-02-11 11:02:57 + --- + + My actual content + MD + end + + it_behaves_like 'a page without front-matter' + end + + context 'the wiki page has invalid YAML in fenced block' do + let(:content) do + <<~MD + --- + invalid-use-of-reserved-indicator: @text + --- + + My actual content + MD + end + + it_behaves_like 'a page without front-matter' + end + end + describe '.unhyphenize' do it 'removes hyphens from a name' do name = 'a-name--with-hyphens' @@ -155,8 +279,8 @@ describe WikiPage do end describe '#validate_path_limits' do - let(:max_title) { described_class::MAX_TITLE_BYTES } - let(:max_directory) { described_class::MAX_DIRECTORY_BYTES } + let(:max_title) { Gitlab::WikiPages::MAX_TITLE_BYTES } + let(:max_directory) { Gitlab::WikiPages::MAX_DIRECTORY_BYTES } where(:character) do ['a', 'รค', '๐'] @@ -296,7 +420,7 @@ describe WikiPage do subject.update(content: "new content") page = wiki.find_page(title) - expect(page.content).to eq('new content') + expect([subject.content, page.content]).to all(eq('new content')) end it "returns true" do @@ -333,7 +457,7 @@ describe WikiPage do subject.update(content: new_content) page = wiki.find_page('test page') - expect(page.content).to eq("new content") + expect([subject.content, page.content]).to all(eq("new content")) end it "updates the title of the page" do @@ -342,7 +466,75 @@ describe WikiPage do subject.update(title: new_title) page = wiki.find_page(new_title) - expect(page.title).to eq(new_title) + expect([subject.title, page.title]).to all(eq(new_title)) + end + + describe 'updating front_matter' do + shared_examples 'able to update front-matter' do + it 'updates the wiki-page front-matter' do + title = subject.title + content = subject.content + subject.update(front_matter: { slugs: ['x'] }) + page = wiki.find_page(title) + + expect([subject, page]).to all( + have_attributes( + front_matter: include(slugs: include('x')), + content: content + )) + end + end + + it_behaves_like 'able to update front-matter' + + context 'the front matter is too long' do + let(:new_front_matter) do + { + title: generate(:wiki_page_title), + slugs: Array.new(51).map { FFaker::Lorem.characters(512) } + } + end + + it 'raises an error' do + expect { subject.update(front_matter: new_front_matter) }.to raise_error(described_class::FrontMatterTooLong) + end + end + + context 'the front-matter feature flag is not enabled' do + before do + disable_front_matter + end + + it 'does not update the front-matter' do + content = subject.content + subject.update(front_matter: { slugs: ['x'] }) + + page = wiki.find_page(subject.title) + + expect([subject, page]).to all(have_attributes(front_matter: be_empty, content: content)) + end + + context 'but it is enabled for the project' do + before do + enable_front_matter_for_project + end + + it_behaves_like 'able to update front-matter' + end + end + + it 'updates the wiki-page front-matter and content together' do + title = subject.title + content = 'totally new content' + subject.update(content: content, front_matter: { slugs: ['x'] }) + page = wiki.find_page(title) + + expect([subject, page]).to all( + have_attributes( + front_matter: include(slugs: include('x')), + content: content + )) + end end it "returns true" do |