8cd2db38cc
Deploy Polska Lokalnie / deploy (push) Successful in 11s
Wycena trafia do AccountShell, jak pozostale narzedzia: gosc widzi sama strone, zalogowany takze lewe menu konta. Test nie zakladal juz menu i dlatego nie przechodzil. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
503 lines
22 KiB
TypeScript
503 lines
22 KiB
TypeScript
import { test, expect, type Page } from '@playwright/test';
|
|
import { ROUTES, negotiationPath, ADMIN_CONVERSATION_SLUG, conversationPath, newConversationPath } from '../src/routes';
|
|
|
|
// Standard projektu (AGENTS.md): kazdy widok ma wlasny URL obslugiwany przez React Router,
|
|
// a nawigacja odbywa sie przez <Link>/<NavLink>. Te testy pilnuja tej zasady.
|
|
|
|
const ADMIN = { email: 'admin@softspm.com', password: 'Admin123!' };
|
|
|
|
const PUBLIC_ROUTES = [
|
|
ROUTES.home,
|
|
ROUTES.buy,
|
|
ROUTES.rent,
|
|
ROUTES.sell,
|
|
ROUTES.valuation,
|
|
ROUTES.priceHistory,
|
|
ROUTES.districtRanking,
|
|
ROUTES.negotiation,
|
|
ROUTES.creditCalculator,
|
|
ROUTES.map,
|
|
ROUTES.services,
|
|
ROUTES.companies,
|
|
ROUTES.guides,
|
|
ROUTES.guideBuying,
|
|
ROUTES.login,
|
|
ROUTES.loginForgot,
|
|
ROUTES.register,
|
|
ROUTES.registerPrivate,
|
|
ROUTES.registerCompany,
|
|
];
|
|
|
|
const PROTECTED_ROUTES = [
|
|
ROUTES.account,
|
|
ROUTES.favorites,
|
|
ROUTES.messages,
|
|
conversationPath(ADMIN_CONVERSATION_SLUG),
|
|
newConversationPath(1),
|
|
ROUTES.add,
|
|
ROUTES.admin,
|
|
`${ROUTES.admin}/leady`,
|
|
];
|
|
|
|
async function goto(page: Page, path: string) {
|
|
await page.goto(path, { waitUntil: 'domcontentloaded' });
|
|
await page.locator('main').first().waitFor({ state: 'attached' });
|
|
// ProtectedRoute dociaga profil z /auth/me - poczekaj, az skonczy stan ladowania
|
|
await page.locator('.route-loading').waitFor({ state: 'detached' }).catch(() => {});
|
|
await page.waitForTimeout(400);
|
|
}
|
|
|
|
async function login(page: Page) {
|
|
await goto(page, ROUTES.login);
|
|
await page.getByPlaceholder('Wpisz swój adres e-mail').fill(ADMIN.email);
|
|
await page.getByPlaceholder('Wpisz swoje hasło').fill(ADMIN.password);
|
|
await page.getByRole('button', { name: 'Zaloguj się', exact: true }).click();
|
|
// token w localStorage to pewny dowod zalogowania - adres moze sie jeszcze zmieniac
|
|
await page.waitForFunction(() => Boolean(window.localStorage.getItem('polskalokalnie-auth-token')));
|
|
await page.waitForFunction(() => window.location.pathname !== '/logowanie');
|
|
}
|
|
|
|
test.describe('Trasy publiczne', () => {
|
|
for (const path of PUBLIC_ROUTES) {
|
|
test(`bezposrednie wejscie na ${path} (F5 / nowa karta / wklejony link)`, async ({ page }) => {
|
|
await goto(page, path);
|
|
expect(new URL(page.url()).pathname).toBe(path);
|
|
await expect(page.locator('main')).not.toBeEmpty();
|
|
});
|
|
}
|
|
|
|
test('nieznany adres pokazuje strone 404', async ({ page }) => {
|
|
await goto(page, '/adres-ktory-nie-istnieje');
|
|
await expect(page.locator('.not-found-page')).toBeVisible();
|
|
});
|
|
|
|
test('odswiezenie strony zachowuje widok', async ({ page }) => {
|
|
await goto(page, ROUTES.districtRanking);
|
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
|
expect(new URL(page.url()).pathname).toBe(ROUTES.districtRanking);
|
|
});
|
|
});
|
|
|
|
test.describe('Lista firm i uslug (/firmy)', () => {
|
|
// Do serwisu nie dolaczyla jeszcze zadna firma. Dopoki tak jest, /firmy pokazuje SAMO zaproszenie -
|
|
// bez naglowka, licznika, chipow kategorii i wyszukiwarki (pokazywalyby zera i filtrowaly pustke).
|
|
// Gdy pojawi sie pierwsza firma, gorna czesc wraca i te testy trzeba rozszerzyc o karty.
|
|
test('wejscie na /firmy pokazuje samo zaproszenie', async ({ page }) => {
|
|
await goto(page, ROUTES.companies);
|
|
await expect(page.locator('.companies-none')).toBeVisible();
|
|
await expect(page.locator('.directory-card')).toHaveCount(0);
|
|
await expect(page.locator('.companies-head')).toHaveCount(0);
|
|
await expect(page.locator('.companies-filters')).toHaveCount(0);
|
|
await expect(page.locator('.service-mini-search')).toHaveCount(0);
|
|
});
|
|
|
|
test('zaproszenie przejmuje role naglowka H1', async ({ page }) => {
|
|
await goto(page, ROUTES.companies);
|
|
const headings = page.locator('.companies-page h1');
|
|
await expect(headings).toHaveCount(1);
|
|
await expect(headings).toContainText('Nie mamy jeszcze żadnych firm');
|
|
});
|
|
|
|
test('kategoria z query stringu trafia do komunikatu', async ({ page }) => {
|
|
await goto(page, `${ROUTES.companies}?kategoria=remonty`);
|
|
await expect(page.locator('.companies-none')).toContainText('Remont i wykończenie');
|
|
|
|
await goto(page, ROUTES.companies);
|
|
await expect(page.locator('.companies-none')).toContainText('w naszej bazie');
|
|
});
|
|
|
|
test('nieznana kategoria nie wywraca widoku', async ({ page }) => {
|
|
await goto(page, `${ROUTES.companies}?kategoria=nie-ma-takiej`);
|
|
await expect(page.locator('.companies-none')).toBeVisible();
|
|
await expect(page.locator('.companies-none')).toContainText('w naszej bazie');
|
|
});
|
|
|
|
// Kategorii usług jeszcze nie obsługujemy, więc kafelek prowadzi na stronę zgłoszenia
|
|
// reklamowego (/reklama), a nie do listy firm - z kategorią przeniesioną w query stringu.
|
|
test('"Zobacz firmy" prowadzi na strone reklamy z wybrana kategoria', async ({ page }) => {
|
|
await goto(page, ROUTES.services);
|
|
const link = page.locator('.service-category-card', { hasText: 'Remont i wykończenie' }).getByRole('link');
|
|
await expect(link).toHaveAttribute('href', '/reklama?kategoria=remonty');
|
|
await link.click();
|
|
await page.waitForFunction(() => window.location.pathname === '/reklama');
|
|
await expect(page.locator('.advertising-input.select select')).toHaveValue('Remont i wykończenie');
|
|
});
|
|
|
|
test('"Zobacz wszystkie" prowadzi na /firmy', async ({ page }) => {
|
|
await goto(page, ROUTES.services);
|
|
const link = page.locator('.services-section .section-head', { hasText: 'Polecane firmy' }).getByRole('link');
|
|
await expect(link).toHaveAttribute('href', ROUTES.companies);
|
|
await link.click();
|
|
await page.waitForFunction(() => window.location.pathname === '/firmy');
|
|
await expect(page.locator('.companies-none')).toBeVisible();
|
|
});
|
|
|
|
test('Wstecz i Dalej dzialaja na filtrze kategorii', async ({ page }) => {
|
|
await goto(page, ROUTES.services);
|
|
await page.locator('.service-category-card', { hasText: 'Finanse' }).getByRole('link').click();
|
|
await page.waitForFunction(() => window.location.search.includes('kategoria=finanse'));
|
|
|
|
await page.goBack({ waitUntil: 'domcontentloaded' });
|
|
await page.waitForFunction(() => window.location.pathname === '/firmy-i-uslugi');
|
|
|
|
await page.goForward({ waitUntil: 'domcontentloaded' });
|
|
await page.waitForFunction(() => window.location.search.includes('kategoria=finanse'));
|
|
});
|
|
});
|
|
|
|
test.describe('Nawigacja przez linki', () => {
|
|
test('menu glowne to <a href> - mozna otworzyc w nowej karcie', async ({ page }) => {
|
|
await goto(page, ROUTES.home);
|
|
for (const [label, expected] of [
|
|
['Kupuję', ROUTES.buy],
|
|
['Wynajmuję', ROUTES.rent],
|
|
['Poradniki', ROUTES.guides],
|
|
['Firmy i usługi', ROUTES.services],
|
|
] as const) {
|
|
const link = page.getByRole('link', { name: label, exact: true }).first();
|
|
await expect(link).toHaveAttribute('href', expected);
|
|
}
|
|
});
|
|
|
|
test('aktywna pozycja menu wynika z adresu', async ({ page }) => {
|
|
await goto(page, ROUTES.buy);
|
|
await expect(page.getByRole('link', { name: 'Kupuję', exact: true }).first()).toHaveClass(/active/);
|
|
});
|
|
|
|
test('CTA naglowka maja poprawne adresy', async ({ page }) => {
|
|
await goto(page, ROUTES.home);
|
|
await expect(page.locator('a.post-button')).toHaveAttribute('href', ROUTES.add);
|
|
await expect(page.getByRole('link', { name: 'Moje konto' })).toHaveAttribute('href', ROUTES.login);
|
|
});
|
|
|
|
test('CTA w tresci strony sa linkami z href', async ({ page }) => {
|
|
await goto(page, ROUTES.sell);
|
|
await expect(page.locator('a.sell-primary')).toHaveAttribute('href', ROUTES.add);
|
|
await expect(page.locator('.sell-valuation-card a')).toHaveAttribute('href', ROUTES.valuation);
|
|
});
|
|
|
|
test('karta oferty ma prawdziwy link do strony oferty', async ({ page }) => {
|
|
await goto(page, ROUTES.buy);
|
|
await page.locator('.real-result-card').first().waitFor();
|
|
const card = page.locator('.real-result-card').first();
|
|
const href = await card.locator('.card-stretched-link').getAttribute('href');
|
|
expect(href).toMatch(/^\/oferta\/\d+$/);
|
|
await expect(card.locator('a.real-card-cta')).toHaveAttribute('href', href!);
|
|
});
|
|
|
|
test('klik w serce na karcie nie nawiguje', async ({ page }) => {
|
|
await goto(page, ROUTES.buy);
|
|
await page.locator('.real-result-card').first().waitFor();
|
|
await page.locator('.real-result-card').first().locator('.real-favorite-button').click();
|
|
await page.waitForTimeout(700);
|
|
expect(new URL(page.url()).pathname).toBe(ROUTES.buy);
|
|
});
|
|
|
|
test('klik w menu zmienia adres, Wstecz i Dalej dzialaja', async ({ page }) => {
|
|
await goto(page, ROUTES.home);
|
|
await page.getByRole('link', { name: 'Kupuję', exact: true }).first().click();
|
|
await page.waitForFunction(() => window.location.pathname === '/kupno');
|
|
|
|
await page.getByRole('link', { name: 'Poradniki', exact: true }).first().click();
|
|
await page.waitForFunction(() => window.location.pathname === '/poradniki');
|
|
|
|
await page.goBack({ waitUntil: 'domcontentloaded' });
|
|
await page.waitForFunction(() => window.location.pathname === '/kupno');
|
|
|
|
await page.goForward({ waitUntil: 'domcontentloaded' });
|
|
await page.waitForFunction(() => window.location.pathname === '/poradniki');
|
|
});
|
|
});
|
|
|
|
test.describe('Standard: brak atrap linkow', () => {
|
|
const PAGES = [ROUTES.home, ROUTES.services, ROUTES.companies, ROUTES.guides, ROUTES.sell, ROUTES.buy];
|
|
|
|
for (const path of PAGES) {
|
|
test(`${path} nie zawiera href="#" ani javascript:void`, async ({ page }) => {
|
|
await goto(page, path);
|
|
const bad = await page.locator('a[href="#"], a[href^="javascript:"]').count();
|
|
expect(bad).toBe(0);
|
|
});
|
|
}
|
|
});
|
|
|
|
test.describe('Trasy chronione', () => {
|
|
test('bez logowania przekierowuja na /logowanie', async ({ page }) => {
|
|
for (const path of PROTECTED_ROUTES) {
|
|
await goto(page, path);
|
|
expect(new URL(page.url()).pathname).toBe(ROUTES.login);
|
|
}
|
|
});
|
|
|
|
test('po zalogowaniu wracamy na zamierzona strone', async ({ page }) => {
|
|
await goto(page, ROUTES.accountPriceAlerts);
|
|
expect(new URL(page.url()).pathname).toBe(ROUTES.login);
|
|
|
|
await page.getByPlaceholder('Wpisz swój adres e-mail').fill(ADMIN.email);
|
|
await page.getByPlaceholder('Wpisz swoje hasło').fill(ADMIN.password);
|
|
await page.getByRole('button', { name: 'Zaloguj się', exact: true }).click();
|
|
|
|
await page.waitForFunction(() => window.location.pathname === '/konto/alerty-cenowe');
|
|
});
|
|
|
|
test('zakladki panelu admina maja wlasne adresy i przezywaja F5', async ({ page }) => {
|
|
await login(page);
|
|
await goto(page, ROUTES.admin);
|
|
|
|
await page.locator('.admin-nav a', { hasText: 'Leady' }).first().click();
|
|
await page.waitForFunction(() => window.location.pathname === '/admin/leady');
|
|
|
|
await page.reload({ waitUntil: 'domcontentloaded' });
|
|
await page.locator('.admin-nav').first().waitFor({ state: 'attached' });
|
|
expect(new URL(page.url()).pathname).toBe('/admin/leady');
|
|
});
|
|
|
|
test('nieznana sekcja panelu admina pokazuje 404', async ({ page }) => {
|
|
await login(page);
|
|
await goto(page, `${ROUTES.admin}/nie-ma-takiej-sekcji`);
|
|
await expect(page.locator('.not-found-page')).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('Layout konta', () => {
|
|
// Kazda pozycja lewego menu ma otwierac sie tak samo jak /konto/wyszukiwania,
|
|
// czyli razem z widocznym menu konta.
|
|
const ACCOUNT_PAGES = [
|
|
ROUTES.account,
|
|
ROUTES.accountSearches,
|
|
ROUTES.favorites,
|
|
ROUTES.accountPriceAlerts,
|
|
ROUTES.comparison,
|
|
ROUTES.messages,
|
|
ROUTES.accountMeetings,
|
|
ROUTES.accountListings,
|
|
ROUTES.accountSettings,
|
|
ROUTES.notifications,
|
|
ROUTES.accountHelpContact,
|
|
];
|
|
|
|
// Narzedzia publiczne dzialaja jak /kupno czy /wynajem - bez menu konta.
|
|
const PUBLIC_TOOLS = [ROUTES.valuation, ROUTES.priceHistory, ROUTES.districtRanking, ROUTES.negotiation];
|
|
|
|
test('lewe menu konta jest widoczne na wszystkich stronach konta', async ({ page }) => {
|
|
await login(page);
|
|
for (const path of ACCOUNT_PAGES) {
|
|
await goto(page, path);
|
|
await expect(page.locator('.account-sidebar'), `brak lewego menu na ${path}`).toBeVisible();
|
|
}
|
|
});
|
|
|
|
test('lewe menu nie przeskakuje miedzy stronami konta', async ({ page }) => {
|
|
await login(page);
|
|
const positions: Array<{ path: string; x: number; width: number }> = [];
|
|
|
|
for (const path of ACCOUNT_PAGES) {
|
|
await goto(page, path);
|
|
const box = await page.locator('.account-sidebar').first().boundingBox();
|
|
positions.push({ path, x: Math.round(box!.x), width: Math.round(box!.width) });
|
|
}
|
|
|
|
const first = positions[0];
|
|
for (const pos of positions) {
|
|
expect(pos.x, `menu przesuniete na ${pos.path}`).toBe(first.x);
|
|
expect(pos.width, `inna szerokosc menu na ${pos.path}`).toBe(first.width);
|
|
}
|
|
});
|
|
|
|
// Narzedzia sa publiczne: gosc widzi sama strone, a zalogowany takze lewe menu konta -
|
|
// dzieki temu menu nie znika po otwarciu narzedzia z panelu.
|
|
test('narzedzia publiczne: bez menu dla goscia, z menu po zalogowaniu', async ({ page }) => {
|
|
for (const path of PUBLIC_TOOLS) {
|
|
await goto(page, path);
|
|
await expect(page.locator('.account-sidebar'), `menu konta u goscia na ${path}`).toHaveCount(0);
|
|
}
|
|
|
|
await login(page);
|
|
for (const path of PUBLIC_TOOLS) {
|
|
await goto(page, path);
|
|
await expect(page.locator('.account-sidebar'), `brak menu konta na ${path}`).toBeVisible();
|
|
}
|
|
});
|
|
|
|
// Bezpieczenstwo i edycja profilu byly osobnymi stronami powtarzajacymi tresc ustawien.
|
|
// Teraz sa sekcjami /konto/ustawienia, a stare adresy maja przekierowywac.
|
|
test('stare adresy profilu i bezpieczenstwa przekierowuja do ustawien', async ({ page }) => {
|
|
await login(page);
|
|
for (const path of [ROUTES.accountSecurity, ROUTES.accountProfileEdit]) {
|
|
await goto(page, path);
|
|
expect(new URL(page.url()).pathname, `${path} nie przekierowal`).toBe(ROUTES.accountSettings);
|
|
}
|
|
});
|
|
|
|
test('ustawienia pokazuja dane podane przy rejestracji i nie dubluja sekcji', async ({ page }) => {
|
|
await login(page);
|
|
await goto(page, ROUTES.accountSettings);
|
|
|
|
// E-mail konta jest wypelniony automatycznie i nie da sie go tu zmienic.
|
|
const emailInput = page.locator('.settings-card input[disabled]').first();
|
|
await expect(emailInput).toHaveValue(ADMIN.email);
|
|
|
|
// Nick nadany przy zakladaniu konta jest widoczny w formularzu.
|
|
await expect(page.getByText('polskalokalnie.pl/u/', { exact: false }).first()).toBeVisible();
|
|
|
|
// Jezyk komunikacji wystepowal wczesniej dwa razy na jednym ekranie.
|
|
await expect(page.getByText('Język komunikacji', { exact: true })).toHaveCount(1);
|
|
// Bezpieczenstwo jest dokladnie jedna sekcja, nie karta + osobna strona.
|
|
await expect(page.locator('section[aria-label="Bezpieczeństwo"]')).toHaveCount(1);
|
|
});
|
|
|
|
test('menu uzytkownika w naglowku ma pozycje ulozone w jednej linii', async ({ page }) => {
|
|
await login(page);
|
|
await goto(page, ROUTES.home);
|
|
await page.locator('.account-menu-trigger').click();
|
|
|
|
const items = page.locator('.account-popover a');
|
|
await expect(items.first()).toBeVisible();
|
|
|
|
for (let i = 0; i < await items.count(); i += 1) {
|
|
const box = await items.nth(i).boundingBox();
|
|
// ikona obok tekstu daje ~42px; zawiniecie do dwoch linii daje wyraznie wiecej
|
|
expect(Math.round(box!.height), 'pozycja menu zawinela sie do dwoch linii').toBeLessThan(56);
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Naglowek', () => {
|
|
test('zostaje przyklejony do gory przy przewijaniu', async ({ page }) => {
|
|
for (const path of [ROUTES.home, ROUTES.buy, ROUTES.guides]) {
|
|
await goto(page, path);
|
|
await page.evaluate(() => window.scrollTo(0, 1400));
|
|
await page.waitForTimeout(300);
|
|
const box = await page.locator('.header').boundingBox();
|
|
expect(Math.round(box!.y), `naglowek odjechal na ${path}`).toBe(0);
|
|
}
|
|
});
|
|
|
|
test('logo prowadzi na strone glowna i pokazuje nowa nazwe', async ({ page }) => {
|
|
await goto(page, ROUTES.buy);
|
|
const brand = page.locator('a.brand');
|
|
await expect(brand).toHaveAttribute('href', ROUTES.home);
|
|
await expect(brand).toContainText('Polska Lokalnie');
|
|
await expect(brand).toContainText('ogłoszenia za darmo');
|
|
});
|
|
});
|
|
|
|
test.describe('Wiadomosci', () => {
|
|
test('"Napisz wiadomosc" w ogloszeniu otwiera rozmowe pod wlasnym adresem', async ({ page }) => {
|
|
await login(page);
|
|
await goto(page, ROUTES.buy);
|
|
await page.locator('.real-result-card').first().waitFor();
|
|
const href = await page.locator('.real-result-card .card-stretched-link').first().getAttribute('href');
|
|
await goto(page, href!);
|
|
|
|
await page.getByRole('button', { name: /Napisz wiadomość/ }).first().click();
|
|
await page.waitForFunction(() => /^\/wiadomosci\/nowa\/\d+$/.test(window.location.pathname));
|
|
// Adres szkicu dziala po odswiezeniu - rozmowa nie zalezy od stanu nawigacji.
|
|
await page.reload();
|
|
await expect(page.locator('.messages-composer input[type=text]')).toBeVisible();
|
|
});
|
|
|
|
test('nieistniejaca rozmowa wraca na liste wiadomosci', async ({ page }) => {
|
|
await login(page);
|
|
await goto(page, conversationPath(999999));
|
|
await page.waitForFunction(() => window.location.pathname === '/wiadomosci');
|
|
});
|
|
});
|
|
|
|
test.describe('Logowanie i rejestracja', () => {
|
|
test('kroki maja wlasne adresy, a Wstecz wraca do poprzedniego kroku', async ({ page }) => {
|
|
await goto(page, ROUTES.login);
|
|
await page.getByRole('button', { name: 'Zarejestruj się' }).first().click();
|
|
await page.waitForFunction(() => window.location.pathname === '/rejestracja');
|
|
await page.locator('.register-choice-option').first().click();
|
|
await page.waitForFunction(() => window.location.pathname === '/rejestracja/osoba-prywatna');
|
|
await page.goBack();
|
|
await page.waitForFunction(() => window.location.pathname === '/rejestracja');
|
|
});
|
|
|
|
test('ekran "sprawdz poczte" bez rejestracji wraca do rejestracji', async ({ page }) => {
|
|
await goto(page, ROUTES.registerPending);
|
|
await page.waitForFunction(() => window.location.pathname === '/rejestracja');
|
|
});
|
|
});
|
|
|
|
test.describe('Wycena', () => {
|
|
test('kroki maja wlasne adresy, a dane przetrwaja odswiezenie', async ({ page }) => {
|
|
await goto(page, ROUTES.valuation);
|
|
await page.locator('.valuation-form-section input').first().fill('Warszawa');
|
|
await page.getByRole('button', { name: /Dalej/ }).click();
|
|
await page.waitForFunction(() => window.location.pathname === '/wycena/szczegoly');
|
|
await page.reload();
|
|
await page.goBack();
|
|
await page.waitForFunction(() => window.location.pathname === '/wycena');
|
|
await expect(page.locator('.valuation-form-section input').first()).toHaveValue('Warszawa');
|
|
});
|
|
|
|
test('pusty wynik prowadzi do kroku z brakujacymi danymi', async ({ page }) => {
|
|
await goto(page, ROUTES.valuationResult);
|
|
await expect(page.locator('.valuation-result-hero strong').first()).toHaveText('Brakuje danych do wyceny');
|
|
await page.locator('.valuation-missing-item').first().click();
|
|
await page.waitForFunction(() => window.location.pathname === '/wycena');
|
|
});
|
|
});
|
|
|
|
test.describe('Negocjacje', () => {
|
|
test('"Ile moge utargowac?" w ogloszeniu sprzedazy otwiera analize pod adresem z numerem', async ({ page }) => {
|
|
await goto(page, ROUTES.buy);
|
|
await page.locator('.real-result-card').first().waitFor();
|
|
const href = await page.locator('.real-result-card .card-stretched-link').first().getAttribute('href');
|
|
await goto(page, href!);
|
|
|
|
await page.getByRole('link', { name: /Ile mogę utargować/ }).click();
|
|
await page.waitForFunction(() => /^\/negocjacje\/\d+$/.test(window.location.pathname));
|
|
await page.reload();
|
|
await expect(page.locator('.negotiation-offer h2')).toBeVisible();
|
|
await expect(page.locator('.negotiation-range')).not.toContainText('Pobieramy', { timeout: 15000 });
|
|
});
|
|
|
|
test('nieistniejace ogloszenie pokazuje komunikat', async ({ page }) => {
|
|
await goto(page, negotiationPath(999999));
|
|
await expect(page.getByText('Nie znaleźliśmy tego ogłoszenia')).toBeVisible();
|
|
});
|
|
});
|
|
|
|
test.describe('Standard: przyciski robia to, co obiecuja', () => {
|
|
test('wyszukiwarka poradnikow trzyma fraze w adresie i przezywa F5', async ({ page }) => {
|
|
await goto(page, ROUTES.guides);
|
|
await page.locator('.guides-search input').fill('kredyt');
|
|
await page.locator('.guides-search button').click();
|
|
await page.waitForFunction(() => window.location.search.includes('szukaj=kredyt'));
|
|
await page.reload();
|
|
await expect(page.locator('section[aria-label="Wyniki wyszukiwania"]')).toContainText('kredyt');
|
|
});
|
|
|
|
test('"Szukaj na biezacej mapie" zaweza liste do ofert z mapy', async ({ page }) => {
|
|
await goto(page, ROUTES.buy);
|
|
await page.locator('.map-card').first().waitFor();
|
|
await page.getByRole('button', { name: /Szukaj na bieżącej mapie/ }).first().click();
|
|
await page.waitForFunction(() => window.location.search.includes('obszar='));
|
|
await expect(page.locator('.map-area-note')).toBeVisible();
|
|
await page.locator('.map-area-note button').click();
|
|
await page.waitForFunction(() => !window.location.search.includes('obszar='));
|
|
});
|
|
|
|
test('porownanie trzyma wybrane oferty w adresie', async ({ page }) => {
|
|
await login(page);
|
|
await goto(page, ROUTES.buy);
|
|
await page.locator('.real-result-card').first().waitFor();
|
|
const href = await page.locator('.real-result-card .card-stretched-link').first().getAttribute('href');
|
|
const listingId = Number(href!.split('/').pop());
|
|
await goto(page, `${ROUTES.comparison}?oferty=${listingId}`);
|
|
await expect(page.locator('.comparison-main')).toContainText('Zobacz ogłoszenie');
|
|
await page.reload();
|
|
await expect(page.locator('.comparison-main')).toContainText('Zobacz ogłoszenie');
|
|
});
|
|
|
|
test('kanaly kontaktu w pomocy to prawdziwe linki mailto i tel', async ({ page }) => {
|
|
await login(page);
|
|
await goto(page, ROUTES.accountHelpContact);
|
|
await expect(page.locator('a.help-contact-channel-action[href^="mailto:"]')).toHaveCount(1);
|
|
await expect(page.locator('a.help-contact-channel-action[href^="tel:"]')).toHaveCount(1);
|
|
});
|
|
});
|