05 Jan

Intro summary and details tags in HTML5

The <details> and the <summary> is the easiest way to create an accordean.

Show Spoiler

The Zebra did it!


    <summary>Show Spoiler</summary>
    <p>The Zebra did it!</p>

You can get it to work in line as well…

<style type="text/css">
.inline {
.inline summary {
    text-decoration: underline;
    text-decoration-style: dotted;
.inline span:before {
.inline span:after {

<div>I want to learn
<details class="inline">
    <span>Hyper Text Markup Language</span>
08 Oct

Puppeteer and ShadowDOM

If you are testing an app – be it React, Angular or Vue – and you are using an library that uses shadow DOM to create elements(say, Ionic), you’ll find that there are elements(within the shadow dom) that can’t be accessed using ‘waitForSelector‘ call. If you try making an waitFor or waitForSelector call, it will be a rejected promise.

I ran into this issue while testing an error message that used ion-toast – that component used shadow dom to display the message. I’m sure Ionic uses it in other things like popups and dialogs. So to test that you must be able to peirce the shadow DOM.

There are already suggestions in Puppeteer to create calls like shadow$ or shadow$$. But till that becomes live, you can fix this issue using the query-selector-shadow-dom library.

This library workes with other tools like…

  • WebdriverIO
  • Playwright
  • Puppeteer

Here is an example of it in action…

const puppeteer = require('puppeteer');
const {  QueryHandler } = require("query-selector-shadow-dom/plugins/puppeteer");
(async () => {
    try {
        await puppeteer.__experimental_registerCustomQueryHandler('shadow', QueryHandler);
        const browser = await puppeteer.launch({
            headless: false,
            devtools: true
        const page = await browser.newPage()
        await page.goto('')

        // ensure btn exists and return it
        await page.waitForSelector("shadow/.btn-in-shadow-dom");
        const btn = await page.("shadow/.btn-in-shadow-dom");
        await btn.click();

        // check btn was clicked (this page expected btn to change text of output)
        const outputSpan = await page.("shadow/.output");
        const text = await page.evaluate((output) => output.innerText, outputSpan);
        // prints the text from the output

        await browser.close()
    } catch (e) {


Here are a few examples of how you can use query-selector-shadow-dom with Puppeteer

24 Nov

Database Data to Download Variables

Gets data from a MySql database, splits the data into separate columns, then uses one column in a URL to download something – and uses other column to name the file thats downloaded

for i in (mysql -u root Project_Madapp -sNe 'SELECT CONCAT(id,",",name) AS yo FROM City WHERE type="actual"'); do parts=({i//,/ }); wget -O "{parts[1]}.csv" "http://localhost/student_allocation_csv.php?format=csv&city_id={parts[0]}"; done

16 Mar

Closing WhatsApp on Nokia E72

First install the app called MobileGuard. Its a cool app. I’ll recommend it even if you want to keep whatsapp. Next, open MobileGuard, and go to Clean Spam > Memory Cleaning > Clear in Batch > Select WhatsApp. Now select the ‘Off’ option. This should close the app and all its services

Keep in mind that whatsapp will start again when you restart your phone. If you want to turn that off, go to Boot Mgr in Mobile Guard and disable it.