require 'cgi' require 'rails_helper' RSpec.describe 'Wiki history integrity', type: :request do let!(:user) { create_member_user! } def auth_headers user { 'X-Transfer-Code' => user.inheritance_code } end def create_wiki_page title:, body: 'body', message: 'init', user: self.user Wiki::Commit.create_content!( tag_name: TagName.create!(name: title), body:, created_by_user: user, message:) end describe 'POST /wiki' do it 'creates wiki_page, wiki_revision, and wiki_version atomically' do expect { post '/wiki', params: { title: 'wiki_history_create_atomic', body: "a\nb\nc", message: 'initial commit', }, headers: auth_headers(user) } .to change(WikiPage, :count).by(1) .and change(WikiRevision, :count).by(1) .and change(WikiVersion, :count).by(1) expect(response).to have_http_status(:created) page = WikiPage.find(json.fetch('id')) revision = page.current_revision version = page.wiki_versions.order(:version_no).last expect(page.title).to eq('wiki_history_create_atomic') expect(page.body).to eq("a\nb\nc") expect(revision).to be_content expect(revision.message).to eq('initial commit') expect(revision.lines_count).to eq(3) expect(version).to have_attributes( version_no: 1, event_type: 'create', title: 'wiki_history_create_atomic', body: "a\nb\nc", reason: 'initial commit', created_by_user_id: user.id ) end it 'returns 422 and creates nothing when normalised body is blank' do expect { post '/wiki', params: { title: 'wiki_history_blank_body', body: "\r\n\r\n", message: 'blank', }, headers: auth_headers(user) } .not_to change(WikiPage, :count) expect(response).to have_http_status(:unprocessable_entity) expect(WikiPage.joins(:tag_name).where(tag_names: { name: 'wiki_history_blank_body' })).not_to exist end it 'returns 422 and creates no partial page when title already exists' do create_wiki_page(title: 'wiki_history_duplicate_title', body: 'first') expect { post '/wiki', params: { title: 'wiki_history_duplicate_title', body: 'second', message: 'duplicate', }, headers: auth_headers(user) } .not_to change(WikiPage, :count) expect(response).to have_http_status(:unprocessable_entity) expect(WikiPage.joins(:tag_name).where(tag_names: { name: 'wiki_history_duplicate_title' }).count).to eq(1) end end describe 'PUT /wiki/:id' do it 'updates body and records wiki_revision and wiki_version' do page = create_wiki_page(title: 'wiki_history_update_body', body: 'before') current_id = page.current_revision.id expect { put "/wiki/#{ page.id }", params: { title: 'wiki_history_update_body', body: 'after', message: 'edit body', base_revision_id: current_id, }, headers: auth_headers(user) } .to change(WikiRevision, :count).by(1) .and change(WikiVersion, :count).by(1) expect(response).to have_http_status(:ok) page.reload version = page.wiki_versions.order(:version_no).last expect(page.title).to eq('wiki_history_update_body') expect(page.body).to eq('after') expect(version).to have_attributes( event_type: 'update', title: 'wiki_history_update_body', body: 'after', reason: 'edit body', created_by_user_id: user.id ) end it 'renames title and records wiki_version with new title' do page = create_wiki_page(title: 'wiki_history_rename_before', body: 'before') current_id = page.current_revision.id expect { put "/wiki/#{ page.id }", params: { title: 'wiki_history_rename_after', body: 'after', message: 'rename', base_revision_id: current_id, }, headers: auth_headers(user) } .to change(WikiRevision, :count).by(1) .and change(WikiVersion, :count).by(1) expect(response).to have_http_status(:ok) page.reload version = page.wiki_versions.order(:version_no).last expect(page.title).to eq('wiki_history_rename_after') expect(page.body).to eq('after') expect(version).to have_attributes( event_type: 'update', title: 'wiki_history_rename_after', body: 'after', reason: 'rename', created_by_user_id: user.id ) end it 'does not change title, body, revision, or version on stale base_revision_id' do page = create_wiki_page(title: 'wiki_history_conflict_page', body: 'first') stale_id = page.current_revision.id Wiki::Commit.content!( page:, body: 'second', created_user: user, message: 'other edit', base_revision_id: stale_id) page.reload current_title = page.title current_body = page.body revision_count = page.wiki_revisions.count version_count = page.wiki_versions.count put "/wiki/#{ page.id }", params: { title: 'wiki_history_conflict_renamed', body: 'third', message: 'stale edit', base_revision_id: stale_id, }, headers: auth_headers(user) expect(response).to have_http_status(:conflict) page.reload expect(page.title).to eq(current_title) expect(page.body).to eq(current_body) expect(page.wiki_revisions.count).to eq(revision_count) expect(page.wiki_versions.count).to eq(version_count) end end end