FIX: Update raw and cooked immediate after edit (#13387)

* Revert "DEV: skips three tests following cc1e73  (#13386)"

This reverts commit 2be201660a.

* FIX: Do not refresh post stream twice

This also improves the test suite and simulates a long running request

* FIX: Update local copy of raw
This commit is contained in:
Bianca Nenciu 2021-06-16 03:50:27 +03:00 committed by GitHub
parent c659e3e95b
commit 3a3a2abdb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 45 deletions

View File

@ -929,6 +929,7 @@ const Composer = RestModel.extend({
editPost(opts) { editPost(opts) {
const post = this.post; const post = this.post;
const oldRaw = post.raw;
const oldCooked = post.cooked; const oldCooked = post.cooked;
let promise = Promise.resolve(); let promise = Promise.resolve();
@ -970,16 +971,14 @@ const Composer = RestModel.extend({
this.set("composeState", SAVING); this.set("composeState", SAVING);
const rollback = throwAjaxError((error) => { const rollback = throwAjaxError((error) => {
post.setProperties({ cooked: oldCooked, staged: false }); post.setProperties({ raw: oldRaw, cooked: oldCooked });
this.appEvents.trigger("post-stream:refresh", { id: post.id });
this.set("composeState", OPEN); this.set("composeState", OPEN);
if (error.jqXHR && error.jqXHR.status === 409) { if (error.jqXHR && error.jqXHR.status === 409) {
this.set("editConflict", true); this.set("editConflict", true);
} }
}); });
post.setProperties({ cooked: props.cooked, staged: true }); post.setProperties({ raw: props.raw, cooked: props.cooked, staged: true });
this.appEvents.trigger("post-stream:refresh", { id: post.id }); this.appEvents.trigger("post-stream:refresh", { id: post.id });
return promise return promise

View File

@ -14,26 +14,23 @@ acceptance("Composer - Edit conflict", function (needs) {
}); });
}); });
QUnit.skip( test("Edit a post that causes an edit conflict", async function (assert) {
"Edit a post that causes an edit conflict", await visit("/t/internationalization-localization/280");
async function (assert) { await click(".topic-post:nth-of-type(1) button.show-more-actions");
await visit("/t/internationalization-localization/280"); await click(".topic-post:nth-of-type(1) button.edit");
await click(".topic-post:nth-of-type(1) button.show-more-actions"); await fillIn(".d-editor-input", "this will 409");
await click(".topic-post:nth-of-type(1) button.edit"); await click("#reply-control button.create");
await fillIn(".d-editor-input", "this will 409"); assert.equal(
await click("#reply-control button.create"); queryAll("#reply-control button.create").text().trim(),
assert.equal( I18n.t("composer.overwrite_edit"),
queryAll("#reply-control button.create").text().trim(), "it shows the overwrite button"
I18n.t("composer.overwrite_edit"), );
"it shows the overwrite button" assert.ok(
); queryAll("#draft-status .d-icon-user-edit"),
assert.ok( "error icon should be there"
queryAll("#draft-status .d-icon-user-edit"), );
"error icon should be there" await click(".modal .btn-primary");
); });
await click(".modal .btn-primary");
}
);
test("Should not send originalText when posting a new reply", async function (assert) { test("Should not send originalText when posting a new reply", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");

View File

@ -348,15 +348,25 @@ acceptance("Composer", function (needs) {
); );
}); });
QUnit.skip("Editing a post stages new content", async function (assert) { test("Editing a post stages new content", async function (assert) {
await visit("/t/internationalization-localization/280"); await visit("/t/internationalization-localization/280");
await click(".topic-post:nth-of-type(1) button.show-more-actions"); await click(".topic-post:nth-of-type(1) button.show-more-actions");
await click(".topic-post:nth-of-type(1) button.edit"); await click(".topic-post:nth-of-type(1) button.edit");
await fillIn(".d-editor-input", "will return empty json"); await fillIn(".d-editor-input", "will return empty json");
await fillIn("#reply-title", "This is the new text for the title"); await fillIn("#reply-title", "This is the new text for the title");
await click("#reply-control button.create");
// when this promise resolves, the request had already started because
// this promise will be resolved by the pretender
const promise = new Promise((resolve) => {
window.resolveLastPromise = resolve;
});
// click to trigger the save, but wait until the request starts
click("#reply-control button.create");
await promise;
// at this point, request is in flight, so post is staged
assert.equal(count(".topic-post.staged"), 1); assert.equal(count(".topic-post.staged"), 1);
assert.ok( assert.ok(
find(".topic-post:nth-of-type(1)")[0].className.includes("staged") find(".topic-post:nth-of-type(1)")[0].className.includes("staged")
@ -365,28 +375,31 @@ acceptance("Composer", function (needs) {
find(".topic-post.staged .cooked").text().trim(), find(".topic-post.staged .cooked").text().trim(),
"will return empty json" "will return empty json"
); );
// finally, finish request and wait for last render
window.resolveLastPromise();
await visit("/t/internationalization-localization/280");
assert.equal(count(".topic-post.staged"), 0);
}); });
QUnit.skip( test("Editing a post can rollback to old content", async function (assert) {
"Editing a post can rollback to old content", await visit("/t/internationalization-localization/280");
async function (assert) { await click(".topic-post:nth-of-type(1) button.show-more-actions");
await visit("/t/internationalization-localization/280"); await click(".topic-post:nth-of-type(1) button.edit");
await click(".topic-post:nth-of-type(1) button.show-more-actions");
await click(".topic-post:nth-of-type(1) button.edit");
await fillIn(".d-editor-input", "this will 409"); await fillIn(".d-editor-input", "this will 409");
await fillIn("#reply-title", "This is the new text for the title"); await fillIn("#reply-title", "This is the new text for the title");
await click("#reply-control button.create"); await click("#reply-control button.create");
assert.ok(!exists(".topic-post.staged")); assert.ok(!exists(".topic-post.staged"));
assert.equal( assert.equal(
find(".topic-post .cooked")[0].innerText, find(".topic-post .cooked")[0].innerText,
"Any plans to support localization of UI elements, so that I (for example) could set up a completely German speaking forum?" "Any plans to support localization of UI elements, so that I (for example) could set up a completely German speaking forum?"
); );
await click(".bootbox.modal .btn-primary"); await click(".bootbox.modal .btn-primary");
} });
);
test("Composer can switch between edits", async function (assert) { test("Composer can switch between edits", async function (assert) {
await visit("/t/this-is-a-test-topic/9"); await visit("/t/this-is-a-test-topic/9");

View File

@ -1,6 +1,7 @@
import Pretender from "pretender"; import Pretender from "pretender";
import User from "discourse/models/user"; import User from "discourse/models/user";
import getURL from "discourse-common/lib/get-url"; import getURL from "discourse-common/lib/get-url";
import { Promise } from "rsvp";
export function parsePostData(query) { export function parsePostData(query) {
const result = {}; const result = {};
@ -479,12 +480,15 @@ export function applyDefaultHandlers(pretender) {
pretender.put("/posts/:post_id/recover", success); pretender.put("/posts/:post_id/recover", success);
pretender.get("/posts/:post_id/expand-embed", success); pretender.get("/posts/:post_id/expand-embed", success);
pretender.put("/posts/:post_id", (request) => { pretender.put("/posts/:post_id", async (request) => {
const data = parsePostData(request.requestBody); const data = parsePostData(request.requestBody);
if (data.post.raw === "this will 409") { if (data.post.raw === "this will 409") {
return response(409, { errors: ["edit conflict"] }); return response(409, { errors: ["edit conflict"] });
} else if (data.post.raw === "will return empty json") { } else if (data.post.raw === "will return empty json") {
return response(200, {}); window.resolveLastPromise();
return new Promise((resolve) => {
window.resolveLastPromise = resolve;
}).then(() => response(200, {}));
} }
data.post.id = request.params.post_id; data.post.id = request.params.post_id;
data.post.version = 2; data.post.version = 2;