Login Sign Up
Advert
Your ad spot
Reserve this exclusive slot for the selected period.
Buy advertising →
Telegram community logo - QA Co-pilot
Added 06 Dec 2025

QA Co-pilot

@qa_copilot
Number of subscribers: 93
Photos: 302
Links: 47
Description:
QA Co-pilot 🚀 Ваш другий пілот у світі тестування. 👨‍💻 Для кого: Для тестувальників-практиків, які хочуть рости. 🎯 Про що: Делегуємо рутину нейромережам, прискорюємо роботу та звільняємо час на головне. ❌ Чого тут немає: Нудної теорії та води.

👥 Number of subscribers

93
Average/Day:: -1
Average/Week:: 0
Average/Month:: +2

👁️ Average views per message

28
Average/Day:: 28
Average/Week:: 26
ERR: 30.11%

📊 Messages per Day

1.3
Last day: 0
Week average: 1.4
Average per day: 1.3

Status change history

Officially not confirmed 2025-12-06

Wall

Telegram statistics channel

👁 24 26-05-25 13:28
⚔️ Битва підходів: Junior vs. QA Architect (Цикли проти Нативних ассертів)Сьогодні розберемо класичну ситуацію: вам треба перевірити масив елементів на сторінці (наприклад, список повідомлень у чаті або таблицю). Як витягнути та перевірити дані, не змусивши ваш тест "гальмувати"? ☕️ Підхід Junior-автоматизатораconst texts = [];const messages = page.locator('.chat-message');const count = await messages.count();for (let i = 0; i < count; i++) { // Повільно витягуємо текст по одному... texts.push(await messages.nth(i).textContent());}expect(texts).toContain('Замовлення успішне'); Чому це антипатерн: Це повільно і крихко. По-перше, count() стріляє миттєво і не чекає на рендер (часто повертає 0). По-друге, кожна ітерація циклу for робить окремий асинхронний запит до браузера. Якщо у чаті 50 повідомлень — тест гарантовано "зависне" на кілька секунд. Підхід QA Architect// Варіант 1: Одразу перевіряємо наявність тексту у списку (з auto-retry)await expect(page.locator('.chat-message')).toContainText(['Замовлення успішне']);// Варіант 2: Якщо масив реально потрібен для хитрої логікиconst allTexts = await page.locator('.chat-message').allTextContents(); Чому це шедевр: Швидкість світла і стабільність. Playwright виконує allTextContents() або toContainText() за одну мілісекунду на рівні браузерного рушія, перехоплюючи весь масив одразу. Крім того, веб-ассерт автоматично зачекає (до 5 секунд), поки потрібне повідомлення не з'явиться в DOM, що рятує від Flaky-тестів.Золоте правило: Якщо ви пишете цикл for для перебору UI-елементів у Playwright — зупиніться. З імовірністю 99% ви робите щось не так і для цього вже є нативний оптимізований метод.А як ви працюєте зі списками елементів? 👇
👁 26 26-05-22 07:39
💩 Код з душком: If/Else у тестах (або Тест із роздвоєнням особистості)Привіт, екіпаж! П'ятниця — традиційний час вивітрювати "смердючий" код з репозиторіїв. Сьогодні препаруємо гріх, який перетворює ваші автотести на непередбачуваний хаос. Поговоримо про умовну логіку (Conditional Testing). ☕️Знайдіть проблему в цьому тесті:// Як пишуть джуни (Антипатерн "Ворожка")test('Повинен додати товар у кошик', async ({ page }) => { await page.goto('/product/123'); // "Якщо раптом вилізе промо-банер, то закриємо його..." if (await page.locator('.promo-popup').isVisible()) { await page.locator('.close-promo').click(); } await page.locator('.add-to-cart').click();}); Чому цей код тхне:Ви щойно вбили детермінованість тесту (його передбачуваність). Метод isVisible() у Playwright не чекає! Він стріляє миттєво.Якщо ваш фронтенд на Angular рендерить цей поп-ап за 300 мілісекунд, на момент перевірки isVisible() поверне false. Тест проігнорує блок if і піде клікати на кнопку кошика. АЛЕ саме в цю мілісекунду поп-ап з'являється на екрані, перекриває кнопку, і ваш тест падає з помилкою Element is intercepted.Ви перезапускаєте тест — сервер відповідає швидше, поп-ап з'являється миттєво, if спрацьовує, тест "зелений". Вітаю, ви створили еталонний Flaky-тест! Як це виглядає після код-рев'ю Senior-інженера:Тест має бути прямою лінією. Якщо банер можна відключити (через cookie або API-мок) — відключаємо. Якщо ж це неконтрольований поп-ап, використовуємо нативну "магію" Playwright 1.42+:// Ідеально чистий код (Playwright addLocatorHandler)test('Повинен додати товар у кошик', async ({ page }) => { // 1. Вчимо Playwright автоматично реагувати на перешкоду, ЯКЩО вона з'явиться await page.addLocatorHandler( page.locator('.promo-popup'), async () => { await page.locator('.close-promo').click(); } ); await page.goto('/product/123'); // 2. Тест залишається абсолютно лінійним, ніяких if/else! await page.locator('.add-to-cart').click();}); Золоте правило: Ніколи не використовуйте if / else для синхронізації UI чи обробки випадкових елементів на сторінці. Автотест — це не алгоритм пошуку шляху, це жорсткий сценарій. Контролюйте стан додатка, а для асинхронних перешкод делегуйте роботу фреймворку.А скільки if'ів зараз заховано у вашому фреймворку? 👇🔥 — Використовую addLocatorHandler, мої тести прямі як стріла!👀 — Грішу іф-елсами, бо на проді постійно лізуть рандомні банери...🤯 — Тепер я зрозумів, чому мої тести періодично падають на кліках!
👁 29 26-05-15 06:03
💩 Код з душком: Перехресне запилення, або Чому ваші тести падають у CI/CDПривіт, екіпаж! П'ятниця — час для генерального прибирання у ваших репозиторіях. Сьогодні ми препаруємо одну з найнебезпечніших інженерних хвороб — sharing state (обмін станом) між тестами. Це той випадок, коли ви використовуєте глобальні змінні для передачі даних від одного тесту до іншого. ☕️Знайдіть проблему в цьому коді:// Як пишуть джуни (Антипатерн "Глобальний наркоман")// Десь у глобальному скоупі файлуlet lastCreatedUserId: string;test('Тест 1: Створити юзера', async ({ request }) => { const newUser = await request.post('/api/users', { data: { name: 'Bro' } }); // Зберігаємо ID у глобальну змінну для наступного тесту lastCreatedUserId = (await newUser.json()).id;});test('Тест 2: Видалити створеного юзера', async ({ request }) => { // Використовуємо ID, який створив ПОПЕРЕДНІЙ тест await request.delete(`/api/users/${lastCreatedUserId}`);}); Чому цей код тхне:На вашій локальній машині це може працювати. Але в CI/CD Playwright за замовчуванням запускає тести паралельно (в різних воркерах/процесах).Коли воркер №2 почне виконувати «Тест 2», глобальна змінна lastCreatedUserId у його процесі буде порожньою (undefined), бо «Тест 1» виконувався в іншому воркері №1. У вас "червоний" пайплайн, а ви витрачаєте пів дня, намагаючись зрозуміти, чому тест на видалення не бачить ID. Як це виглядає після код-рев'ю Senior-інженера:// Ідеально чистий код (Повна атомарність)test('Повинен видаляти користувача', async ({ request }) => { // 1. Створюємо юзера ІЗОЛЬОВАНО всередині одного тесту const newUser = await request.post('/api/users', { data: { name: 'IsolatedBro' } }); const userId = (await newUser.json()).id; // 2. Використовуємо ID тут же await request.delete(`/api/users/${userId}`);}); Золоте правило: Кожен тест має бути повністю атомарним. Тест має сам створювати потрібні дані, виконувати дію і сам за собою прибирати (якщо це необхідно). Жодних глобальних змінних для передачі даних!А ваші тести бігають у паралель, чи ви боїтесь, що вони "перепиляться" даними? 👇🔥 — Тільки атомарні тести, тільки паралельний запуск!👀 — Грішимо глобальними змінними, тому запускаємо по одному...🤯 — Мої тести впали вчора, тепер я знаю чому!
👁 30 26-05-14 13:05
🔍 Рентген співбесіди: «Ми вам передзвонимо» або що насправді шукає рекрутерБуває так: ти розклав по поличках роботу Playwright, пояснив різницю між Promise.all та Promise.allSettled, і навіть задизайнив фреймворк на ходу. Але в кінці отримуєш стандартне «дякуємо, ми на зв'язку».Давайте «просвітимо» рентгеном, які приховані патології в софт-скілах або технічних відповідях найчастіше стають причиною відмови.🦴 «Скелет в шафі» технічного боргуКоли тебе питають про архітектуру, а ти розповідаєш лише про те, як писати селектори. Рекрутер бачить не Middle AQA, а людину, яка просто автоматизує ручні кейси без розуміння стратегії.🔹Діагноз: Відсутність системного мислення.🔹Лікування: Говори про CI/CD, звіти, інтеграцію з Test IT та обробку флекі-тестів за допомогою ретраїв. 🧪 «Магічне» тестування (No-Code ілюзія)Якщо ти занадто сильно покладаєшся на ШІ-інструменти або no-code рішення, не розуміючи, як вони працюють «під капотом», на рентгені це виглядає як купа іржавих шестерень, заклеєних синьою ізолентою.🔹Діагноз: Низька технічна експертиза.🔹Лікування: Покажи, що ти знаєш DOM-дерево Angular краще за будь-який дрон, і можеш написати чистий код навіть на серветці. 🧬 Ізоляція замість інтеграціїКандидат ідеально знає свій «чорний ящик» API, але поняття не має, як дані потрапляють з фронтенда в БД або як працює аутентифікація через Bearer токени.🔹Діагноз: Обмежений кругозір.🔹Лікування: Вивчай DevTools як свої п'ять пальців — від нетворк-графів до спуфінгу геолокації. 🚩 Red Flags на знімку: 🔹Хардкод таймаути: Якщо на питання про очікування ти кажеш await page.waitForTimeout(5000), десь у світі сумує один лід.🔹Ігнорування витоків пам'яті: Тести проходять, але браузер «зжирає» всю RAM на сервері? Рентген покаже це як «цифрових привидів», що душать твоє залізо. Порада дня: Співбесіда — це не допит, а перевірка сумісності твого «коду» з культурою команди. Будь як той архітектор з майбутнього: спокійним, впевненим і завжди з чітким планом автоматизації.А які «діагнози» ставили вам на співбесідах? Пишіть у коментарях! 👇#QA #AQA #Testing #Interview #Career #Playwright #Angular
👁 29 26-05-13 13:01
🗂 Ультимативна шпаргалка: Локатори Playwright (2018 vs 2026)Коротка шпаргалка про те, як відучити себе писати "крихкі" тести. Зберігайте в обране і кидайте на код-рев'ю. ☕️ Застарілий підхід (CSS / XPath) Сучасний підхід (User-Facing API)1️⃣ Кнопки та посилання page.locator('.btn-primary.submit') page.getByRole('button', { name: 'Зберегти' }) Чому: Перевіряє не лише текст, а й доступність (Accessibility). Якщо розробник випадково зробить кнопку div-ом, тест впаде.2️⃣ Пошук статичного тексту page.locator('//div/span[contains(text(), "Успіх")]') page.getByText('Успіх', { exact: true }) Чому: Працює незалежно від того, як фронтендер перетасує div та span у компоненті.3️⃣ Специфічні блоки (картки, аватари) page.locator('.user-card .avatar-img') page.getByTestId('user-avatar') Чому: CSS-класи належать дизайнерам (вони їх змінюють). Атрибути data-testid належать QA — їх ніхто не чіпає.4️⃣ Точковий пошук у списках/таблицях (Chaining) page.locator('.table-row:has-text("Ivan") >> .delete-btn') page.getByRole('row', { name: 'Ivan' }).getByRole('button', { name: 'Видалити' }) Чому: Читається як звичайна англійська мова, нуль магії.Золоте правило: Шукайте елементи так, як їх шукає реальний юзер (за текстом та роллю), а не так, як їх бачить браузер (за селекторами).А на чому сидите ви? 👇🔥 — Тільки getByRole та getByText, класика.👀 — Мій бестфренд — це data-testid.🤬 — Я фанат XPath, мене вже не перевчити!
👁 24 26-05-12 08:42
🧨 Руйнівники IT-міфів #1 МІФ: "QA гальмує розробку"Привіт, екіпаж! Сьогодні беремо найпопулярніше виправдання для скорочення QA-команд і кладемо його на стіл розтину. Не думки, не відчуття — тільки цифри. ☕️🧠 Звідки міф? Продакт дивиться на спринт: розробники кодять, QA "знаходить проблеми" і повертає задачі назад. Здається, що QA — це та ланка, яка сповільнює потік. Логіка зрозуміла. Логіка хибна. 🔬 Що кажуть дані 1️⃣ Правило ×100 (IBM Systems Sciences Institute):Виправлення дефекту на стадії дизайну коштує в 6 разів дешевше, ніж під час імплементації. Той самий баг, знайдений після релізу в продакшені — у 100 разів дорожче, ніж на стадії підтримки. 2️⃣ Простими числами: баг вартістю $100 на етапі планування → $10 000 у продакшені — бо він тягне за собою каскадні ефекти в суміжних системах, потребує координації між командами і затримує наступні релізи.3️⃣ Вартість простою:Для enterprise-компаній середня вартість однієї години критичного даунтайму перевищує $300 000. Деякі інциденти легко перетинають позначку $1 млн на годину.4️⃣Реальний кейс з фінтеху:Баг у заокругленні, знайдений QA на стадії тестування, обійшовся у 4 години роботи ($400). Той самий тип помилки, що потрапила у прод, зачепила 12 000 транзакцій — і потягнула за собою екстрений патч, звірку даних і регуляторне розкриття. 5️⃣ Де насправді губиться час розробників:Dev-команди витрачають у середньому 30–50% свого часу на виправлення багів і незапланований rework. Це не QA гальмує — це баги без QA з'їдають половину capacity команди. 📐 Математика для скептиківПравильно побудована QA-програма для команди з 20 розробників коштує $120 000–180 000 на рік. Математика зазвичай виправдовує себе вже в перший квартал.Один інцидент з checkout-сторінкою на e-commerce з трафіком $500K/день при 2% відмов — це $10 000 на день прямих втрат. Тиждень без виявлення — $70 000.Висновок: QA не уповільнює розробку. QA уповільнює потрапляння дефектів у прод — а це принципово різні речі. 💡 Як змінити фрейм в голові у стейкхолдераНе "QA знайшов 12 багів і повернув задачу".А — "QA зекономив команді 3 тижні рефакторингу і $200K потенційних втрат".QA — це не гальмо. Це страховий поліс, який окупається щоразу, коли ти його не використовуєш. 🛡 А як у вас реагують на QA в команді?🔥 — QA — повноцінні партнери, нас залучають з першого дня спринту👀 — "Ну давайте швиденько протестуємо перед релізом"🤯 — "Нащо QA, у нас розробники самі тестують"
👁 25 26-05-11 12:29
⚔️ Битва підходів: Junior vs. QA Architect (Page Object Model — правильна архітектура)Сьогодні розбираємо тему, яку всі "знають", але мало хто робить правильно — Page Object Model. Різниця між Junior і Architect тут не в тому, чи використовувати POM. А в тому, що саме ховати всередині. ☕️ Підхід Junior-автоматизатора (POM як "папка для локаторів")// pages/LoginPage.tsexport class LoginPage { readonly page: Page; constructor(page: Page) { this.page = page; } async fillEmail(email: string) { await this.page.locator('#email').fill(email); } async fillPassword(password: string) { await this.page.locator('#password').fill(password); } async clickSubmit() { await this.page.locator('#submit').click(); }}// tests/login.spec.tstest('Логін з валідними даними', async ({ page }) => { const loginPage = new LoginPage(page); await loginPage.fillEmail('[email protected]'); await loginPage.fillPassword('qwerty123'); await loginPage.clickSubmit(); await expect(page.locator('.dashboard-title')).toBeVisible();}); Чому це антипатерн: По-перше: Page Object перетворився на тонку обгортку над локаторами — і нічого більше. Вся логіка взаємодії досі живе в тесті. По-друге, тест знає забагато: він знає послідовність дій, знає що перевіряти, знає як влаштована сторінка. Якщо завтра #submit стане [data-testid="login-btn"] — йдеш шукати всі місця в тестах руками. По-третє: такий POM не дає жодної ізоляції — це просто перейменовані page.locator() виклики. Підхід QA Architect (POM як сервісний шар)// pages/LoginPage.tsexport class LoginPage { private readonly emailInput = this.page.getByLabel('Email'); private readonly passwordInput = this.page.getByLabel('Password'); private readonly submitButton = this.page.getByRole('button', { name: 'Sign in' }); private readonly errorMessage = this.page.getByTestId('auth-error'); constructor(private readonly page: Page) {} // Публічний API сторінки — одна дія, один метод async login(email: string, password: string): Promise<void> { await this.emailInput.fill(email); await this.passwordInput.fill(password); await this.submitButton.click(); } async expectErrorMessage(text: string): Promise<void> { await expect(this.errorMessage).toHaveText(text); }}// pages/DashboardPage.tsexport class DashboardPage { private readonly title = this.page.getByRole('heading', { name: 'Dashboard' }); constructor(private readonly page: Page) {} async expectLoaded(): Promise<void> { await expect(this.title).toBeVisible(); }}// tests/login.spec.tstest('Логін з валідними даними', async ({ page }) => { const loginPage = new LoginPage(page); const dashboardPage = new DashboardPage(page); await loginPage.login('[email protected]', 'qwerty123'); await dashboardPage.expectLoaded();});test('Логін з невалідним паролем', async ({ page }) => { const loginPage = new LoginPage(page); await loginPage.login('[email protected]', 'wrongpass'); await loginPage.expectErrorMessage('Invalid credentials');}); Чому це шедевр:Тест читається як специфікація, а не як інструкція для браузера. Page Object інкапсулює всю логіку взаємодії — тест не знає жодного локатора. Локатори побудовані на семантиці (getByRole, getByLabel) — стійкі до рефакторингу верстки. Assertions теж живуть у Page Object — тест перевіряє поведінку, а не деталі реалізації. Зміна UI = правка в одному файлі, а не хірургія по всьому репозиторію. Золоте правило: Page Object — це не папка для локаторів. Це публічний API вашої сторінки. Якщо ваш тест досі знає про #submit або .dashboard-title — у вас не POM, у вас ілюзія абстракції.А який рівень POM у вас на проєкті?🔥 — Повна інкапсуляція: тести не знають жодного локатора, тільки методи👀 — Десь між: локатори в POM є, але логіка частково тече в тести🤬 — POM є у назві папки, але по суті — просто locator() обгорнутий в клас
👁 30 26-05-08 12:41
⚔️ Битва підходів: Junior vs. QA Architect (Як ми готуємо тестові дані)Сьогодні в нашій "Битві підходів" розбираємо найдорожчий і найповільніший етап будь-якого E2E тестування — підготовку тестових даних (Data Setup або Preconditions). ☕️Уявімо задачу: нам треба протестувати видалення користувача з таблиці. Підхід Junior-автоматизатора (Через UI)test('Повинен видаляти користувача', async ({ page }) => { // 1. Спочатку створюємо юзера через інтерфейс (марнуємо 10 секунд) await page.locator('#add-btn').click(); await page.locator('#name').fill('Test QA'); await page.locator('#save').click(); await expect(page.locator('.toast')).toHaveText('Створено!'); // 2. І тільки тепер починаємо сам тест на ВИДАЛЕННЯ await page.locator('#delete-btn-Test-QA').click(); await expect(page.locator('.row')).not.toContainText('Test QA');}); Чому це архітектурна катастрофа: По-перше, ви спалюєте гроші компанії на інфраструктуру. Цей тест йтиме 15 секунд замість трьох.По-друге, ви створюєте Каскадні падіння (Cascading Failures). Якщо завтра фронтендер випадково зламає форму створення користувача, у вас впаде тест на видалення! Ваш репорт покаже 50 червоних тестів, хоча насправді баг тільки в одному місці. Підхід QA Architect (Через API)test('Повинен видаляти користувача', async ({ page, request }) => { // 1. Б'ємо напряму в бекенд. Створюємо юзера за 50 мілісекунд const res = await request.post('/api/users', { data: { name: 'Test QA' } }); const user = await res.json(); // 2. Ізольовано тестуємо ТІЛЬКИ видалення через UI await page.goto(`/users/${user.id}`); await page.locator(`#delete-btn-${user.id}`).click(); await expect(page.locator('.row')).not.toContainText('Test QA');}); Чому це шедевр:Тест атомарний. Він перевіряє рівно одну фічу — видалення. Підготовка даних займає мілісекунди. Якщо форма створення зламана, цей тест все одно пройде і доведе, що механізм видалення працює ідеально. Золоте правило: Інтерфейс користувача (UI) створений для тестування самого UI. Використовувати UI для підготовки даних (Preconditions) — це як забивати цвяхи мікроскопом. Для цього є API та прямі запити до бази даних.А як у вас на проєкті генеруються дані перед E2E тестами? 👇🔥 — Тільки API / База даних! Наші тести летять як ракета.👀 — Робимо через UI... Так, тести йдуть по 2 години, але в нас "повна імітація юзера"!🤬 — У нас взагалі один юзер [email protected] на всю команду, хто перший зайшов, той і тестує!
👁 27 26-05-07 12:49
🎙 Рентген співбесіди: "Чорний ящик", або Питання, яке валить 80% Middle QAЗапускаємо нову рубрику «Рентген співбесіди», де ми розбираємо каверзні питання з технічних інтерв'ю та аналізуємо, що насправді хочуть почути від вас ліди. ☕️Сьогодні на операційному столі класична пастка для перевірки архітектурного мислення.Питання від інтерв'юера:"Ви тестуєте наш бекенд. Він розраховує вартість доставки, звертаючись до стороннього API (наприклад, FedEx або Нової Пошти). Доступу до їхньої бази у вас немає, тестового середовища у них теж немає, а кожен ваш запит до їхнього API коштує бізнесу реальних грошей. Ваші дії?" Як відповідає Junior / Слабкий Middle (Червоний прапорець): 1️⃣ "Ну, я попрошу розробників щось придумати або зробити мені тестовий енв." (Перекладання відповідальності).2️⃣ "Буду тестувати обережно, щоб не витратити багато грошей." (Відсутність розуміння автоматизації та навантаження).3️⃣ "Замокаю запити на фронтенді (в Cypress/Playwright), щоб фронт не смикав бекенд." (Катастрофа! Ви залишили бекенд узагалі без тестування). Ліду не потрібен тестувальник, який боїться системи. Йому потрібен інженер, який вміє ізолювати систему. Як відповідає Senior QA (Ідеальна відповідь):"Я не буду чіпати фронтенд. Я ізолюю наш бекенд від зовнішнього світу за допомогою Mock-сервера (наприклад, WireMock або Mountebank)." Далі ви добиваєте інтерв'юера трьома кроками: 1️⃣ Підміна реальності (Stubbing): Я попрошу DevOps (або сам через Docker) підняти локальний WireMock. Скажу бекенду: "Тепер ти ходиш не на api.fedex.com, а на localhost:8080". І на цьому локальному сервері я налаштую заглушки: якщо бекенд питає ціну для Києва — повертай JSON із цифрою 100.2️⃣ Тестування хаосу (Fault Injection):Реальне API може "впасти". Я налаштую свій WireMock так, щоб він повертав 500 Internal Server Error або, ще краще, робив затримку (Delay) у 15 секунд. І я перевірю, чи не "ляже" наш власний бекенд через таймаути і чи не заблокується наша база даних в очікуванні відповіді.3️⃣ Контрактне тестування:Щоб мої заглушки не застаріли, я ініціюю написання Contract Tests. Ми будемо раз на добу перевіряти структуру реального API постачальника, щоб переконатися, що вони не змінили поле price на cost без попередження. Висновок: Цим питанням ліди перевіряють, чи розумієте ви різницю між клієнтськими моками (на фронті) та інфраструктурними моками (на рівні бекенду). Senior QA — це ілюзіоніст, який може створити для бекенду ідеально контрольовану віртуальну реальність.А як би ви відповіли на це питання до прочитання поста? 👇🔥 — WireMock — наше все, завжди ізолюю сторонні API!👀 — Я б сказав про моки на фронтенді... Тепер зрозумів помилку.🤯 — Я б просто тестував на проді. Гуляти так гуляти!
👁 30 26-05-01 10:37
Шпаргалка QA: 5 фішок Chrome DevTools, про які ви (можливо) не знали 🛠Якщо ваш дебаг обмежується вкладками Elements та Console, ви втрачаєте 80% потужності браузера. Зберігайте чек-ліст для суворого тестування:1️⃣ DOM Breakpoints (Хто змінив мій код?)Кнопка несподівано зникає або змінює колір, а ви не розумієте чому?Як: ПКМ на елемент в HTML -> Break on -> attribute modifications. Браузер намертво зупинить виконання JS рівно в ту мілісекунду, коли якийсь скрипт спробує змінити цей елемент, і покаже рядок коду винуватця. 2️⃣ Local Overrides (Тестування без бекенду)Вам треба перевірити, як фронтенд обробить помилку 500, але бекенд працює ідеально?Як: Вкладка Network -> ПКМ на запит -> Override content. Тепер ви можете написати власний кривий JSON або поміняти статус-код. Браузер буде підміняти реальну відповідь сервера вашим фейком на льоту. (Забудьте про складні налаштування Charles). 3️⃣ Sensor Simulation (Телепортація)Тестуєте локалізацію чи пуш-сповіщення за часом?Як: Натисніть Esc у DevTools, відкрийте меню з трьома крапками -> Sensors. Ви можете в один клік змінити свою геолокацію (наприклад, на Токіо) та змінити системну таймзону. Ідеально для тестування багів з датами. 4️⃣ Copy as Fetch (Миттєвий Postman)Побачили складний запит в Network і хочете покрутити його руками?Як: ПКМ на запит -> Copy -> Copy as fetch. Вставляєте це прямо в Console або будь-який термінал, і запит повторюється з усіма потрібними токенами та куками. 5️⃣ CPU Throttling (Симуляція дешевого смартфона)У вас на MacBook Pro (M3) все літає, а юзери скаржаться на "тормоза"?Як: Вкладка Performance -> шестірня (Capture settings) -> CPU: 4x / 6x slowdown. Тільки так можна реально перевірити, наскільки важкий ваш Angular/React додаток для звичайних пристроїв.