Puppeteer এবং সিলেক্টরের প্রতি এর দৃষ্টিভঙ্গি
Puppeteer হল Node-এর জন্য একটি ব্রাউজার অটোমেশন লাইব্রেরি: এটি আপনাকে একটি সহজ এবং আধুনিক জাভাস্ক্রিপ্ট API ব্যবহার করে একটি ব্রাউজার নিয়ন্ত্রণ করতে দেয়।
ব্রাউজারের সবচেয়ে গুরুত্বপূর্ণ কাজ হল, অবশ্যই, ওয়েব পেজ ব্রাউজ করা। এই টাস্ক অটোমেট করার অর্থ হল ওয়েবপেজের সাথে ইন্টার্যাকশন অটোমেট করা।
Puppeteer-এ, স্ট্রিং-ভিত্তিক সিলেক্টর ব্যবহার করে DOM এলিমেন্টের জন্য কোয়েরি করে এবং এলিমেন্টে ক্লিক বা টাইপ করার মতো অ্যাকশন পারফর্ম করে এটি করা হয়। যেমন, developer.google.com খুলে সার্চ বক্স খুঁজে puppetaria সার্চ করার স্ক্রিপ্ট এইরকম দেখতে হতে পারে:
(async () => {
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://developers.google.com/', { waitUntil: 'load' });
// Find the search box using a suitable CSS selector.
const search = await page.$('devsite-search > form > div.devsite-search-container');
// Click to expand search box and focus it.
await search.click();
// Enter search string and press Enter.
await search.type('puppetaria');
await search.press('Enter');
})();
তাই, কোয়েরি সিলেক্টর ব্যবহার করে কীভাবে এলিমেন্ট শনাক্ত করা হয় তা Puppeteer অভিজ্ঞতার একটি গুরুত্বপূর্ণ অংশ। এখনও পর্যন্ত, Puppeteer-এ সিলেক্টরগুলি CSS এবং XPath সিলেক্টরের মধ্যে সীমাবদ্ধ ছিল যা, যদিও এক্সপ্রেশনালি খুব শক্তিশালী, স্ক্রিপ্টে ব্রাউজার ইন্টার্যাকশন বজায় রাখার জন্য ত্রুটি থাকতে পারে।
সিনট্যাকটিক বনাম সেম্যান্টিক সিলেক্টর
CSS বাছাইকারী সিনট্যাক্টিক প্রকৃতির হয়; এগুলি DOM ট্রি-র টেক্সচুয়াল উপস্থাপনার অভ্যন্তরীণ কাজের সাথে ঘনিষ্ঠভাবে যুক্ত থাকে, কারণ এগুলি DOM থেকে আইডি ও ক্লাস নেম রেফার করে। তাই, ওয়েব ডেভেলপারদের জন্য পৃষ্ঠার কোনও এলিমেন্টে স্টাইল যোগ বা পরিবর্তন করার জন্য এটি একটি অবিচ্ছেদ্য টুল, তবে এই প্রসঙ্গে পৃষ্ঠার এবং তার DOM ট্রির উপর ডেভেলপারের সম্পূর্ণ কন্ট্রোল থাকে।
অন্যদিকে, Puppeteer স্ক্রিপ্ট হল কোনও পৃষ্ঠার এক্সটার্নাল অবজারভার, তাই এই প্রসঙ্গে CSS বাছাইকারী ব্যবহার করা হলে, পৃষ্ঠাটি কীভাবে প্রয়োগ করা হয়েছে সেই সম্পর্কে এটি লুকানো অনুমান প্রবর্তন করে, যার উপর Puppeteer স্ক্রিপ্টের কোনও নিয়ন্ত্রণ নেই।
এর ফলে, এই ধরনের স্ক্রিপ্ট ভঙ্গুর হতে পারে এবং সোর্স কোড পরিবর্তনের জন্য সংবেদনশীল হতে পারে। ধরা যাক, কেউ body এলিমেন্টের তৃতীয় চাইল্ড হিসেবে <button>Submit</button> নোড থাকা ওয়েব অ্যাপ্লিকেশনের অটোমেটেড টেস্টিংয়ের জন্য Puppeteer স্ক্রিপ্ট ব্যবহার করেন। টেস্ট কেসের একটি স্নিপেট এইরকম দেখতে হতে পারে:
const button = await page.$('body:nth-child(3)'); // problematic selector
await button.click();
এখানে, আমরা সাবমিট বোতামটি খুঁজে পেতে 'body:nth-child(3)' সিলেক্টর ব্যবহার করছি, তবে এটি ওয়েবপৃষ্ঠার এই ভার্সনের সাথে শক্তভাবে আবদ্ধ। পরে বোতামের উপরে কোনও এলিমেন্ট যোগ করা হলে, এই সিলেক্টর আর কাজ করে না!
This is not news to test writers: Puppeteer users already attempt to pick selectors that are robust to such changes. Puppetaria-এর মাধ্যমে, আমরা ব্যবহারকারীদের এই অনুসন্ধানে একটি নতুন টুল দিই।
Puppeteer এখন CSS সিলেক্টরের উপর নির্ভর না করে অ্যাক্সেসিবিলিটি ট্রি কোয়েরি করার উপর ভিত্তি করে একটি বিকল্প কোয়েরি হ্যান্ডলার সহ শিপ করে। এখানে মূল দর্শন হল যে আমরা যে কংক্রিট এলিমেন্টটি বেছে নিতে চাই সেটি যদি পরিবর্তিত না হয়, তাহলে সংশ্লিষ্ট অ্যাক্সেসিবিলিটি নোডও পরিবর্তিত হওয়া উচিত নয়।
আমরা এই ধরনের সিলেক্টরকে "ARIA সিলেক্টর" বলি এবং অ্যাক্সেসিবিলিটি ট্রির কম্পিউটেড অ্যাক্সেসযোগ্য নাম ও ভূমিকার জন্য কোয়েরি করার সুবিধা দিই। CSS সিলেক্টরের তুলনায়, এই প্রপার্টিগুলি প্রকৃতিগতভাবে সিম্যান্টিক। এগুলি DOM-এর সিনট্যাক্টিক প্রপার্টির সাথে যুক্ত নয়, বরং স্ক্রিন রিডারের মতো সহায়ক প্রযুক্তির মাধ্যমে পৃষ্ঠাটি কীভাবে দেখা হয় তার বর্ণনাকারী।
উপরে টেস্ট স্ক্রিপ্টের উদাহরণে, আমরা পরিবর্তে aria/Submit[role="button"] সিলেক্টর ব্যবহার করে কাঙ্ক্ষিত বোতামটি বেছে নিতে পারি, যেখানে Submit এলিমেন্টের অ্যাক্সেসযোগ্য নামকে বোঝায়:
const button = await page.$('aria/Submit[role="button"]');
await button.click();
এখন, আমরা যদি পরে আমাদের বোতামের টেক্সট কন্টেন্ট Submit থেকে Done-এ পরিবর্তন করার সিদ্ধান্ত নিই, তাহলে পরীক্ষাটি আবার ব্যর্থ হবে, তবে এই ক্ষেত্রে এটি বাঞ্ছনীয়; বোতামের নাম পরিবর্তন করে আমরা পৃষ্ঠার কন্টেন্ট পরিবর্তন করি, এর ভিজ্যুয়াল প্রেজেন্টেশন বা DOM-এ এটি কীভাবে স্ট্রাকচার করা হয়েছে তার বিপরীতে। আমাদের টেস্টে এই ধরনের পরিবর্তন সম্পর্কে আমাদের সতর্ক করা উচিত যাতে নিশ্চিত করা যায় যে এই ধরনের পরিবর্তন ইচ্ছাকৃত।
সার্চ বারের সাথে আরও বড় উদাহরণের দিকে ফিরে গিয়ে, আমরা নতুন aria হ্যান্ডলারের সুবিধা নিতে পারি এবং পরিবর্তন করতে পারি
const search = await page.$('devsite-search > form > div.devsite-search-container');
সাথে
const search = await page.$('aria/Open search[role="button"]');
সার্চ বার খুঁজে পেতে!
আরও সাধারণভাবে, আমরা বিশ্বাস করি যে এই ধরনের ARIA সিলেক্টর ব্যবহার করলে Puppeteer ব্যবহারকারীরা নিম্নলিখিত সুবিধা পেতে পারেন:
- টেস্ট স্ক্রিপ্টে সিলেক্টরকে সোর্স কোড পরিবর্তনের ক্ষেত্রে আরও স্থিতিস্থাপক করে তুলুন।
- টেস্ট স্ক্রিপ্ট আরও সহজে পড়ার উপযোগী করে তুলুন (অ্যাক্সেসযোগ্য নাম হল শব্দার্থিক বর্ণনাকারী)।
- এলিমেন্টে অ্যাক্সেসিবিলিটি প্রপার্টি অ্যাসাইন করার জন্য পেশাদার পদ্ধতিকে উৎসাহিত করুন।
এই নিবন্ধের বাকি অংশে আমরা কীভাবে Puppetaria প্রোজেক্ট প্রয়োগ করেছি তার বিবরণ দেওয়া হয়েছে।
ডিজাইন প্রসেস
ব্যাকগ্রাউন্ড
উপরে যেমন বলা হয়েছে, আমরা অ্যাক্সেসযোগ্য নাম ও ভূমিকা অনুযায়ী এলিমেন্ট কোয়েরি করার সুবিধা চালু করতে চাই। এগুলি হল অ্যাক্সেসিবিলিটি ট্রি-এর প্রপার্টি, যা সাধারণ DOM ট্রি-এর সাথে কাজ করে এবং স্ক্রিন রিডারের মতো ডিভাইসে ওয়েবপেজ দেখানোর জন্য ব্যবহার করা হয়।
অ্যাক্সেসযোগ্য নাম গণনা করার স্পেসিফিকেশন দেখলে বোঝা যায় যে কোনও এলিমেন্টের নাম গণনা করা সহজ কাজ নয়, তাই আমরা শুরু থেকেই ঠিক করেছিলাম যে এর জন্য Chromium-এর বর্তমান ইনফ্রাস্ট্রাকচার আবার ব্যবহার করব।
আমরা কীভাবে এটি প্রয়োগ করার চেষ্টা করেছি
এমনকি Chromium-এর অ্যাক্সেসিবিলিটি ট্রি ব্যবহার করার ক্ষেত্রে নিজেদের সীমাবদ্ধ রাখলেও, Puppeteer-এ ARIA কোয়েরি প্রয়োগ করার বেশ কয়েকটি উপায় আছে। কেন তা দেখতে, প্রথমে দেখা যাক Puppeteer কীভাবে ব্রাউজার নিয়ন্ত্রণ করে।
ব্রাউজার Chrome DevTools Protocol (CDP) নামক প্রোটোকলের মাধ্যমে একটি ডিবাগিং ইন্টারফেস প্রকাশ করে। এটি ভাষা-অ্যাগনস্টিক ইন্টারফেসের মাধ্যমে "পৃষ্ঠাটি আবার লোড করুন" বা "পৃষ্ঠায় জাভাস্ক্রিপ্টের এই অংশটি এক্সিকিউট করুন এবং ফলাফলটি ফেরত দিন" এর মতো কার্যকারিতা প্রকাশ করে।
DevTools ফ্রন্ট-এন্ড এবং Puppeteer, দুটিই ব্রাউজারের সাথে কথা বলার জন্য CDP ব্যবহার করছে। CDP কমান্ড প্রয়োগ করার জন্য, Chrome-এর সব কম্পোনেন্টের মধ্যে DevTools ইনফ্রাস্ট্রাকচার আছে: ব্রাউজারে, রেন্ডারারে এবং আরও অনেক কিছুতে। CDP সঠিক জায়গায় কমান্ড রাউট করার বিষয়টি দেখে।
কোয়েরি করা, ক্লিক করা এবং এক্সপ্রেশন মূল্যায়ন করার মতো Puppeteer অ্যাকশনগুলি Runtime.evaluate-এর মতো CDP কমান্ড ব্যবহার করে করা হয় যা সরাসরি পৃষ্ঠার প্রসঙ্গে JavaScript মূল্যায়ন করে এবং ফলাফল প্রদান করে। অন্যান্য Puppeteer অ্যাকশন যেমন কালার ভিশন ডেফিসিয়েন্সি এমুলেট করা, স্ক্রিনশট নেওয়া বা ট্রেস ক্যাপচার করা, Blink রেন্ডারিং প্রসেসের সাথে সরাসরি যোগাযোগ করার জন্য CDP ব্যবহার করে।

আমাদের কোয়েরি করার কার্যকারিতা প্রয়োগ করার জন্য আমাদের কাছে ইতিমধ্যেই দুটি পথ রয়েছে; আমরা করতে পারি:
- জাভাস্ক্রিপ্টে আমাদের কোয়েরি করার লজিক লিখুন এবং
Runtime.evaluateব্যবহার করে পৃষ্ঠায় সেটি ইনজেক্ট করুন, অথবা - এমন একটি CDP এন্ডপয়েন্ট ব্যবহার করুন যা Blink প্রসেসে সরাসরি অ্যাক্সেসিবিলিটি ট্রি অ্যাক্সেস ও কোয়েরি করতে পারে।
আমরা ৩টি প্রোটোটাইপ প্রয়োগ করেছি:
- JS DOM ট্রাভার্সাল - পৃষ্ঠায় জাভাস্ক্রিপ্ট ইনজেক্ট করার উপর ভিত্তি করে
- Puppeteer AXTree ট্রাভার্সাল - অ্যাক্সেসিবিলিটি ট্রিতে আগে থেকে থাকা CDP অ্যাক্সেস ব্যবহার করার উপর ভিত্তি করে
- CDP DOM ট্রাভার্সাল - অ্যাক্সেসিবিলিটি ট্রি কোয়েরি করার জন্য বিশেষভাবে তৈরি করা নতুন CDP এন্ডপয়েন্ট ব্যবহার করা
JS DOM ট্রাভার্সাল
এই প্রোটোটাইপ DOM-এর সম্পূর্ণ ট্রাভার্সাল করে এবং ট্রাভার্সালের সময় প্রতিটি এলিমেন্টের নাম এবং ভূমিকা খুঁজে পেতে ComputedAccessibilityInfo লঞ্চ ফ্ল্যাগ-এ গেট করা element.computedName এবং element.computedRole ব্যবহার করে।
Puppeteer AXTree ট্র্যাভার্সাল
এখানে, আমরা CDP-এর মাধ্যমে সম্পূর্ণ অ্যাক্সেসিবিলিটি ট্রি ফিরিয়ে আনি এবং Puppeteer-এ এটি ট্রাভার্স করি। এর ফলে অ্যাক্সেসিবিলিটি নোডগুলি DOM নোডে ম্যাপ করা হয়।
CDP DOM ট্রাভার্সাল
এই প্রোটোটাইপের জন্য, আমরা বিশেষভাবে অ্যাক্সেসিবিলিটি ট্রি কোয়েরি করার জন্য একটি নতুন CDP এন্ডপয়েন্ট প্রয়োগ করেছি। এইভাবে, জাভাস্ক্রিপ্টের মাধ্যমে পৃষ্ঠার প্রসঙ্গে না করে C++ ইমপ্লিমেন্টেশনের মাধ্যমে ব্যাক-এন্ডে কোয়েরি করা যেতে পারে।
ইউনিট টেস্ট বেঞ্চমার্ক
নিম্নলিখিত চিত্রটি ৩টি প্রোটোটাইপের জন্য ১০০০ বার চারটি এলিমেন্ট কোয়েরি করার মোট রানটাইম তুলনা করে। বেঞ্চমার্ক ৩টি আলাদা কনফিগারেশনে এক্সিকিউট করা হয়েছে, যেখানে পৃষ্ঠার সাইজ আলাদা ছিল এবং অ্যাক্সেসিবিলিটি এলিমেন্টের ক্যাশিং চালু ছিল কিনা তা দেখা হয়েছে।
এটি স্পষ্ট যে CDP-ব্যাকড কোয়েরি মেকানিজম এবং Puppeteer-এ বাস্তবায়িত অন্য দুটির মধ্যে পারফর্ম্যান্সে যথেষ্ট পার্থক্য রয়েছে এবং পৃষ্ঠার সাইজ বাড়ার সাথে সাথে এই পার্থক্য নাটকীয়ভাবে বৃদ্ধি পায়। JS DOM ট্রাভার্সাল প্রোটোটাইপ অ্যাক্সেসিবিলিটি ক্যাশিং চালু করার ক্ষেত্রে এত ভালভাবে সাড়া দেয় তা দেখা কিছুটা আকর্ষণীয়। ক্যাশিং বন্ধ করা থাকলে, অ্যাক্সেসিবিলিটি ট্রি চাহিদা অনুযায়ী গণনা করা হয় এবং ডোমেন বন্ধ করা থাকলে প্রতিটি ইন্টার্যাকশনের পরে ট্রি বাতিল করে দেওয়া হয়। ডোমেন চালু করলে, Chromium পরিবর্তে কম্পিউটেড ট্রি ক্যাশে করে।
JS DOM ট্রাভার্সালের জন্য, আমরা ট্রাভার্সাল চলাকালীন প্রতিটি এলিমেন্টের জন্য অ্যাক্সেসযোগ্য নাম এবং ভূমিকা জিজ্ঞাসা করি, তাই ক্যাশিং বন্ধ থাকলে, Chromium আমাদের পরিদর্শন করা প্রতিটি এলিমেন্টের জন্য অ্যাক্সেসিবিলিটি ট্রি গণনা করে এবং বাতিল করে। অন্যদিকে, CDP ভিত্তিক পদ্ধতির ক্ষেত্রে, CDP-তে প্রতিটি কলের মধ্যে ট্রি বাতিল করা হয়, অর্থাৎ প্রতিটি কোয়েরির জন্য। এইসব অ্যাপ্রোচ ক্যাশিং চালু করার মাধ্যমেও সুবিধা পায়, কারণ অ্যাক্সেসিবিলিটি ট্রি তখন CDP কল জুড়ে বজায় থাকে, তবে পারফর্ম্যান্স বুস্ট তুলনামূলকভাবে কম হয়।
যদিও এখানে ক্যাশিং চালু করা বাঞ্ছনীয় বলে মনে হচ্ছে, তবে এটি অতিরিক্ত মেমরি ব্যবহারের খরচ সহ আসে। Puppeteer স্ক্রিপ্টের জন্য, যেমন ট্রেস ফাইল রেকর্ড করা, এটি সমস্যাজনক হতে পারে। তাই আমরা ডিফল্ট হিসেবে অ্যাক্সেসিবিলিটি ট্রি ক্যাশিং চালু না করার সিদ্ধান্ত নিয়েছি। ব্যবহারকারীরা CDP অ্যাক্সেসিবিলিটি ডোমেন চালু করে নিজেরাই ক্যাশিং চালু করতে পারবেন।
DevTools টেস্ট স্যুট বেঞ্চমার্ক
আগের বেঞ্চমার্ক থেকে দেখা গেছে যে CDP লেয়ারে আমাদের কোয়েরি করার মেকানিজম প্রয়োগ করলে ক্লিনিক্যাল ইউনিট-টেস্ট পরিস্থিতিতে পারফর্ম্যান্স বুস্ট হয়।
সম্পূর্ণ টেস্ট স্যুট চালানোর আরও বাস্তবসম্মত পরিস্থিতিতে পার্থক্যটি যথেষ্ট স্পষ্ট কিনা তা দেখতে, আমরা জাভাস্ক্রিপ্ট এবং CDP-ভিত্তিক প্রোটোটাইপ ব্যবহার করার জন্য DevTools এন্ড-টু-এন্ড টেস্ট স্যুট প্যাচ করেছি এবং রানটাইম তুলনা করেছি। এই বেঞ্চমার্কে, আমরা [aria-label=…] থেকে কাস্টম কোয়েরি হ্যান্ডলার aria/…-এ মোট ৪৩টি সিলেক্টর পরিবর্তন করেছি, যা আমরা প্রতিটি প্রোটোটাইপ ব্যবহার করে প্রয়োগ করেছি।
টেস্ট স্ক্রিপ্টে কিছু সিলেক্টর একাধিকবার ব্যবহার করা হয়, তাই সুইট রান করার সময় aria কোয়েরি হ্যান্ডলারের এক্সিকিউশনের আসল সংখ্যা ছিল ১১৩। মোট কোয়েরি নির্বাচনের সংখ্যা ছিল ২২৫৩, তাই প্রোটোটাইপের মাধ্যমে কোয়েরি নির্বাচনের মাত্র একটি ভগ্নাংশ ঘটেছে।
উপরের ছবিতে যেমন দেখানো হয়েছে, মোট রানটাইমে একটি স্পষ্ট পার্থক্য রয়েছে। ডেটা থেকে কোনও নির্দিষ্ট সিদ্ধান্তে পৌঁছানো সম্ভব নয়, তবে এটি স্পষ্ট যে এই পরিস্থিতিতেও দুটি প্রোটোটাইপের পারফর্ম্যান্সের মধ্যে পার্থক্য দেখা যায়।
একটি নতুন CDP এন্ডপয়েন্ট
উপরের বেঞ্চমার্কের আলোকে এবং যেহেতু লঞ্চ ফ্ল্যাগ-ভিত্তিক পদ্ধতিটি সাধারণভাবে অবাঞ্ছিত ছিল, তাই আমরা অ্যাক্সেসিবিলিটি ট্রি কোয়েরি করার জন্য একটি নতুন CDP কমান্ড বাস্তবায়নের সাথে এগিয়ে যাওয়ার সিদ্ধান্ত নিয়েছি। এখন, আমাদের এই নতুন এন্ডপয়েন্টের ইন্টারফেস খুঁজে বের করতে হবে।
Puppeteer-এ আমাদের ব্যবহারের ক্ষেত্রে, আর্গুমেন্ট হিসেবে তথাকথিত RemoteObjectIds নেওয়ার জন্য আমাদের এন্ডপয়েন্ট প্রয়োজন এবং পরে সংশ্লিষ্ট DOM এলিমেন্ট খুঁজে পেতে আমাদের সাহায্য করার জন্য, এটি অবজেক্টের একটি তালিকা রিটার্ন করবে যাতে DOM এলিমেন্টের জন্য backendNodeIds থাকে।
নিচের চার্টে যেমন দেখানো হয়েছে, আমরা এই ইন্টারফেসের জন্য বেশ কিছু পদ্ধতি ব্যবহার করে দেখেছি। এর থেকে আমরা বুঝতে পেরেছি যে ফেরত পাঠানো অবজেক্টের সাইজ, অর্থাৎ আমরা সম্পূর্ণ অ্যাক্সেসিবিলিটি নোড ফেরত পাঠিয়েছি নাকি শুধু backendNodeIds, তার মধ্যে কোনও পার্থক্য নেই। অন্যদিকে, আমরা দেখেছি যে এখানে ট্রাভার্সাল লজিক প্রয়োগ করার জন্য আগে থেকে থাকা NextInPreOrderIncludingIgnored ব্যবহার করাটা খুব একটা ভালো সিদ্ধান্ত নয়, কারণ এর ফলে উল্লেখযোগ্যভাবে গতি কমে গেছে।
সবকিছু শেষ করা হচ্ছে
এখন, CDP এন্ডপয়েন্ট সেট-আপ করার পরে, আমরা Puppeteer-এর দিকে কোয়েরি হ্যান্ডলার প্রয়োগ করেছি। এখানে কাজের মূল উদ্দেশ্য ছিল কোয়েরি হ্যান্ডলিং কোডকে রিস্ট্রাকচার করা যাতে পৃষ্ঠার প্রসঙ্গে মূল্যায়ন করা জাভাস্ক্রিপ্টের মাধ্যমে কোয়েরি করার পরিবর্তে সরাসরি CDP-এর মাধ্যমে কোয়েরি সমাধান করা যায়।
এরপরে কী?
নতুন aria হ্যান্ডলার বিল্ট-ইন কোয়েরি হ্যান্ডলার হিসেবে Puppeteer v5.4.0-এর সাথে শিপ করা হয়েছে। ব্যবহারকারীরা কীভাবে এটি তাদের টেস্ট স্ক্রিপ্টে গ্রহণ করেন তা দেখার জন্য আমরা অপেক্ষা করছি এবং আমরা এটিকে আরও বেশি উপযোগী করে তুলতে পারি সে সম্পর্কে আপনার আইডিয়া শোনার জন্য আমরা অপেক্ষা করতে পারছি না!
প্রিভিউ চ্যানেল ডাউনলোড করুন
আপনার ডিফল্ট ডেভেলপমেন্ট ব্রাউজার হিসেবে Chrome Canary, Dev বা Beta ব্যবহার করার কথা বিবেচনা করুন। এইসব প্রিভিউ চ্যানেল আপনাকে লেটেস্ট DevTools ফিচার অ্যাক্সেস করতে দেয়, অত্যাধুনিক ওয়েব প্ল্যাটফর্ম API টেস্ট করতে দেয় এবং আপনার ব্যবহারকারীরা খুঁজে পাওয়ার আগেই আপনার সাইটে সমস্যা খুঁজে পেতে সাহায্য করে!
Chrome DevTools টিমের সাথে যোগাযোগ করুন
DevTools সম্পর্কিত নতুন ফিচার, আপডেট বা অন্য যেকোনও বিষয়ে আলোচনা করতে নিম্নলিখিত বিকল্পগুলি ব্যবহার করুন।
- crbug.com-এ আমাদের মতামত ও ফিচার সংক্রান্ত অনুরোধ পাঠান।
- DevTools-এ আরও বিকল্প > সহায়তা > DevTools-এর সমস্যা সম্পর্কে অভিযোগ জানান বিকল্প ব্যবহার করে DevTools-এর সমস্যা সম্পর্কে অভিযোগ জানান।
- @ChromeDevTools-এ টুইট করুন।
- DevTools YouTube ভিডিওতে নতুন কী আছে বা DevTools YouTube ভিডিও সংক্রান্ত পরামর্শ-এ কমেন্ট করুন।