test(tradein/frontend): колонка ссылки в «05 РЫНОК» — прочерк, а не кнопка-обманка (#2755)
All checks were successful
CI / changes (pull_request) Successful in 15s
CI Trade-In / changes (pull_request) Successful in 15s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m53s
CI / frontend-tests (pull_request) Successful in 2m4s
CI / openapi-codegen-check (pull_request) Successful in 3m19s
All checks were successful
CI / changes (pull_request) Successful in 15s
CI Trade-In / changes (pull_request) Successful in 15s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m53s
CI / frontend-tests (pull_request) Successful in 2m4s
CI / openapi-codegen-check (pull_request) Successful in 3m19s
Проверка на удалённую в предыдущем коммите ветку. Она была недостижима, но выглядела как рабочий элемент интерфейса — некликабельный <span>, стилизованный под кнопку-ссылку «Росреестр ↗». Без проверки ничто не мешает ей вернуться: достаточно снова сделать поле опциональным. Три утверждения через настоящий mapSources: есть URL — ссылка именно на него; URL нет — прочерк и НИ ОДНОЙ ссылки; javascript:-схема отбрасывается safeUrl, и строка тоже получает прочерк, а не кнопку. Проверено, что тест краснеет: возврат «Росреестр ↗» на место прочерка роняет 2 утверждения из 3. Refs #2755
This commit is contained in:
parent
3f0751f0b6
commit
fd1affca8b
1 changed files with 94 additions and 0 deletions
|
|
@ -0,0 +1,94 @@
|
|||
// #2755 — колонка ссылки в таблице аналогов «05 РЫНОК».
|
||||
//
|
||||
// Здесь до этого жила третья ветка: когда `url` приходил `undefined`, рисовался
|
||||
// НЕкликабельный <span>, стилизованный под кнопку-ссылку «Росреестр ↗». Ветка
|
||||
// была недостижима (mapSources всегда ставит `string | null`), но выглядела как
|
||||
// рабочий элемент интерфейса. Ветку убрали, поле сделали обязательным — этот
|
||||
// тест держит обе половины: ссылка есть только там, где есть URL, а строка без
|
||||
// URL получает прочерк, а не кнопку-обманку.
|
||||
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import SourcesView from "../SourcesView";
|
||||
import { mapSources } from "../mappers";
|
||||
import { FIXTURE_ESTIMATE } from "@/app/ui-preview/estimate/fixture";
|
||||
import type { AggregatedEstimate, AnalogLot } from "@/types/trade-in";
|
||||
|
||||
function lot(over: Partial<AnalogLot>): AnalogLot {
|
||||
return {
|
||||
address: "ул. Репина, 73",
|
||||
area_m2: 54,
|
||||
rooms: 2,
|
||||
floor: 7,
|
||||
total_floors: 16,
|
||||
price_rub: 9_700_000,
|
||||
price_per_m2: 179_629,
|
||||
listing_date: "2026-05-12",
|
||||
days_on_market: 18,
|
||||
photo_url: null,
|
||||
source: "avito",
|
||||
source_url: null,
|
||||
distance_m: 120,
|
||||
tier: null,
|
||||
lat: 56.8401,
|
||||
lon: 60.5702,
|
||||
...over,
|
||||
};
|
||||
}
|
||||
|
||||
// Оффлайн-фикстура оценки репозитория с подменёнными аналогами: остальные поля
|
||||
// (sources_used, коридоры, KPI) настоящие, меняем ровно то, что проверяем.
|
||||
function estimateWith(analogs: AnalogLot[]): AggregatedEstimate {
|
||||
return {
|
||||
...FIXTURE_ESTIMATE,
|
||||
analogs,
|
||||
n_analogs: analogs.length,
|
||||
actual_deals: [],
|
||||
};
|
||||
}
|
||||
|
||||
describe("SourcesView — колонка ссылки на оригинал", () => {
|
||||
it("есть URL — кликабельная ссылка на него", () => {
|
||||
const estimate = estimateWith([
|
||||
lot({
|
||||
address: "ул. Репина, 73",
|
||||
source_url: "https://www.avito.ru/ekaterinburg/kvartiry/1",
|
||||
}),
|
||||
]);
|
||||
|
||||
render(<SourcesView data={mapSources(estimate, null)} />);
|
||||
|
||||
const link = screen.getByRole("link", { name: /Источник/ });
|
||||
expect(link).toHaveAttribute(
|
||||
"href",
|
||||
"https://www.avito.ru/ekaterinburg/kvartiry/1",
|
||||
);
|
||||
});
|
||||
|
||||
it("URL нет — прочерк, а не кнопка-обманка «Росреестр ↗»", () => {
|
||||
const estimate = estimateWith([
|
||||
lot({ address: "ул. Викулова, 33", source_url: null }),
|
||||
]);
|
||||
|
||||
render(<SourcesView data={mapSources(estimate, null)} />);
|
||||
|
||||
expect(screen.queryByText(/Росреестр ↗/)).toBeNull();
|
||||
expect(screen.queryByRole("link", { name: /Источник/ })).toBeNull();
|
||||
// Прочерк — единственное содержимое ячейки ссылки в строке аналога.
|
||||
const row = screen.getByText("ул. Викулова, 33").closest("div");
|
||||
expect(row?.textContent).toContain("—");
|
||||
});
|
||||
|
||||
it("javascript:-схема отбрасывается safeUrl — прочерк, а не ссылка", () => {
|
||||
const estimate = estimateWith([
|
||||
lot({ address: "ул. Кирова, 28", source_url: "javascript:alert(1)" }),
|
||||
]);
|
||||
|
||||
render(<SourcesView data={mapSources(estimate, null)} />);
|
||||
|
||||
expect(screen.queryByRole("link", { name: /Источник/ })).toBeNull();
|
||||
const row = screen.getByText("ул. Кирова, 28").closest("div");
|
||||
expect(row?.textContent).toContain("—");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue