fix(mera-public): сверка адреса у хвоста черновика — в коде, не в комментарии
All checks were successful
CI Trade-In / changes (pull_request) Successful in 13s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 16s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m23s
All checks were successful
CI Trade-In / changes (pull_request) Successful in 13s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 16s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m23s
readDraftExtras требует адрес, под который спрашивают, и на несовпадении отдаёт null. Гарантия «потребитель обязан сверить» жила только в комментарии, а takeDraft выходит раньше записи хвоста на пустом и на битом черновике — то есть хвост от предыдущей квартиры доживал до следующего захода в той же вкладке и дождался бы потребителя, который сверить забыл. Плюс два непокрытых кейса: черновик без floor/condition убирает прошлый хвост; хвост не отдаётся чужому адресу.
This commit is contained in:
parent
7b61ecb122
commit
390a6f05b1
3 changed files with 42 additions and 14 deletions
|
|
@ -45,6 +45,9 @@ function submitLandingCard(): string {
|
||||||
// не из своих догадок о наборе вариантов.
|
// не из своих догадок о наборе вариантов.
|
||||||
const conditions = screen.getByRole("group", { name: /состояние/i });
|
const conditions = screen.getByRole("group", { name: /состояние/i });
|
||||||
const chosen = conditions.querySelectorAll("button")[0];
|
const chosen = conditions.querySelectorAll("button")[0];
|
||||||
|
// Без этой проверки пустая группа роняет тест TypeError'ом на textContent —
|
||||||
|
// отказом, по которому не видно, что именно разъехалось с формой.
|
||||||
|
expect(chosen, "в группе «Состояние» не нашлось кнопок").toBeTruthy();
|
||||||
const label = chosen.textContent ?? "";
|
const label = chosen.textContent ?? "";
|
||||||
fireEvent.click(chosen);
|
fireEvent.click(chosen);
|
||||||
|
|
||||||
|
|
@ -56,17 +59,16 @@ function submitLandingCard(): string {
|
||||||
describe("Черновик: обязательные поля переживают переход на /estimate", () => {
|
describe("Черновик: обязательные поля переживают переход на /estimate", () => {
|
||||||
it("этаж и состояние доступны после монтирования целевой страницы", () => {
|
it("этаж и состояние доступны после монтирования целевой страницы", () => {
|
||||||
const condition = submitLandingCard();
|
const condition = submitLandingCard();
|
||||||
expect(condition, "в группе «Состояние» не нашлось кнопок").not.toBe("");
|
|
||||||
|
|
||||||
// Тот самый шаг, который раньше уничтожал оба поля.
|
// Тот самый шаг, который раньше уничтожал оба поля.
|
||||||
render(<EstimateFlow />);
|
render(<EstimateFlow />);
|
||||||
|
|
||||||
const extras = readDraftExtras();
|
// Читаем так же, как будет читать платный шаг: под тот адрес, о котором
|
||||||
|
// спрашивают. Чужому адресу хвост не отдаётся — проверено отдельно в
|
||||||
|
// estimate-draft.test.ts.
|
||||||
|
const extras = readDraftExtras("Екатеринбург, Ленина 5");
|
||||||
expect(extras, "после /estimate от черновика не осталось ничего").not.toBeNull();
|
expect(extras, "после /estimate от черновика не осталось ничего").not.toBeNull();
|
||||||
expect(extras?.floor).toBe("7/16");
|
expect(extras?.floor).toBe("7/16");
|
||||||
expect(extras?.condition).toBe(condition);
|
expect(extras?.condition).toBe(condition);
|
||||||
// Хвост без адреса нельзя предъявлять платному шагу: он не отличит этаж
|
|
||||||
// этой квартиры от этажа предыдущей в той же вкладке.
|
|
||||||
expect(extras?.address).toBe("Екатеринбург, Ленина 5");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,11 @@
|
||||||
import { beforeEach, describe, expect, it } from "vitest";
|
import { beforeEach, describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { normalizeDraftRooms, saveDraft, takeDraft } from "../estimate-draft";
|
import {
|
||||||
|
normalizeDraftRooms,
|
||||||
|
readDraftExtras,
|
||||||
|
saveDraft,
|
||||||
|
takeDraft,
|
||||||
|
} from "../estimate-draft";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Черновик, который лэндинг передаёт на экран проверки.
|
* Черновик, который лэндинг передаёт на экран проверки.
|
||||||
|
|
@ -107,6 +112,24 @@ describe("этаж переживает переход на целевую ст
|
||||||
expect(d?.floor).toBeUndefined();
|
expect(d?.floor).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("черновик без этажа и состояния убирает прошлый хвост", () => {
|
||||||
|
// Иначе этаж от предыдущей квартиры пережил бы свой черновик и лежал бы,
|
||||||
|
// дожидаясь потребителя.
|
||||||
|
saveDraft({ address: "Ленина 5", floor: "7/16", condition: "Хорошее" });
|
||||||
|
takeDraft();
|
||||||
|
saveDraft({ address: "Малышева 51", rooms: "2" });
|
||||||
|
takeDraft();
|
||||||
|
expect(readDraftExtras("Ленина 5")).toBeNull();
|
||||||
|
expect(readDraftExtras("Малышева 51")).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("хвост не отдаётся другому адресу", () => {
|
||||||
|
saveDraft({ address: "Ленина 5", floor: "7/16" });
|
||||||
|
takeDraft();
|
||||||
|
expect(readDraftExtras("Малышева 51")).toBeNull();
|
||||||
|
expect(readDraftExtras("Ленина 5")?.floor).toBe("7/16");
|
||||||
|
});
|
||||||
|
|
||||||
it("этаж не строка — поле выпадает, остальной черновик цел", () => {
|
it("этаж не строка — поле выпадает, остальной черновик цел", () => {
|
||||||
window.sessionStorage.setItem(
|
window.sessionStorage.setItem(
|
||||||
"mera:estimate-draft",
|
"mera:estimate-draft",
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,7 @@ export interface EstimateDraft {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Хвост черновика: то, что собрали на лэндинге, но на `/estimate` не читают.
|
* Хвост черновика: то, что собрали на лэндинге, но на `/estimate` не читают.
|
||||||
*
|
* Адрес лежит здесь вместе с полями — сверку делает `readDraftExtras`.
|
||||||
* Адрес лежит здесь ВМЕСТЕ с полями, а не подразумевается: иначе этаж «7/16»
|
|
||||||
* от квартиры на Ленина переживёт свой черновик и на платном шаге приклеится к
|
|
||||||
* другому дому в той же вкладке. Потребитель обязан сверить адрес, а не верить
|
|
||||||
* тому, что нашёл.
|
|
||||||
*/
|
*/
|
||||||
export interface EstimateDraftExtras {
|
export interface EstimateDraftExtras {
|
||||||
address: string;
|
address: string;
|
||||||
|
|
@ -137,18 +133,25 @@ function saveDraftExtras(draft: EstimateDraft): void {
|
||||||
* Читает, но НЕ забирает: платный шаг может открыться не с первого раза, а
|
* Читает, но НЕ забирает: платный шаг может открыться не с первого раза, а
|
||||||
* второе чтение того же хвоста ничего не портит. Вкладка закроется — исчезнет
|
* второе чтение того же хвоста ничего не портит. Вкладка закроется — исчезнет
|
||||||
* само.
|
* само.
|
||||||
|
*
|
||||||
|
* `expectedAddress` обязателен, а не «желателен»: `takeDraft` выходит раньше
|
||||||
|
* записи хвоста на пустом/битом черновике, поэтому хвост от ПРЕДЫДУЩЕЙ
|
||||||
|
* квартиры доживает до следующего захода в той же вкладке. Сверку нельзя
|
||||||
|
* оставлять на совесть потребителя — не тот адрес, значит ничего нет.
|
||||||
*/
|
*/
|
||||||
export function readDraftExtras(): EstimateDraftExtras | null {
|
export function readDraftExtras(
|
||||||
|
expectedAddress: string,
|
||||||
|
): EstimateDraftExtras | null {
|
||||||
try {
|
try {
|
||||||
const raw = window.sessionStorage.getItem(EXTRAS_KEY);
|
const raw = window.sessionStorage.getItem(EXTRAS_KEY);
|
||||||
if (!raw) return null;
|
if (!raw) return null;
|
||||||
const parsed: unknown = JSON.parse(raw);
|
const parsed: unknown = JSON.parse(raw);
|
||||||
if (typeof parsed !== "object" || parsed === null) return null;
|
if (typeof parsed !== "object" || parsed === null) return null;
|
||||||
const value = parsed as Record<string, unknown>;
|
const value = parsed as Record<string, unknown>;
|
||||||
if (typeof value.address !== "string") return null;
|
if (value.address !== expectedAddress) return null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
address: value.address,
|
address: expectedAddress,
|
||||||
condition:
|
condition:
|
||||||
typeof value.condition === "string" ? value.condition : undefined,
|
typeof value.condition === "string" ? value.condition : undefined,
|
||||||
floor: typeof value.floor === "string" ? value.floor : undefined,
|
floor: typeof value.floor === "string" ? value.floor : undefined,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue