Showing Posts From
Featured

Playwright framework implementation - Part 1
Let’s see the implementation of the playwright framework from the github repo which I created as part of my hands-on effort. Now before I begin, I just wanted to give a little heads-up. This could be a long post and you might have to spend some quality time in order to make the framework up and running. That being said, I will try to reduce the words as much as possible and explain things clear. However, just keep an open mind for now 😉 Couple of things before we start. Let’s quickly spend some time in understanding how the framework is structured, so that you can have a mental picture of how things work when you start making changes. Framework structure . ├── 📁 src │ ├── 📁 apps │ │ └── 📁 common │ │ │ ├── 📁 pages │ │ │ │ ├── 📃 common.page.ts # common page shared b/w apps │ │ └── 📁 app 01 │ │ │ ├── 📁 data │ │ │ │ ├── 📃 page_01.data.json # data for app 01, page 01 │ │ │ │ ├── 📃 page_02.data.json # data for app 01, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.data.json # data for app 01, page n │ │ │ ├── 📁 fixtures │ │ │ │ └── 📃 index.ts # app 01 specific fixtures │ │ │ ├── 📁 locators │ │ │ │ ├── 📃 page_01.locator.ts # locators for app 01, page 01 │ │ │ │ ├── 📃 page_02.locator.ts # locators for app 01, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.locator.ts # locators for app 01, page n │ │ │ ├── 📁 pages │ │ │ │ ├── 📃 page_01.page.ts # functions for app 01, page 01 │ │ │ │ ├── 📃 page_02.page.ts # functions for app 01, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.page.ts # functions for app 01, page n │ │ │ └── 📁 tests │ │ │ │ ├── 📃 page_01.spec.ts # tests for app 01, page 01 │ │ │ │ ├── 📃 page_02.spec.ts # tests for app 01, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.spec.ts # tests for app 01, page n │ │ │ ├── 📃 config.json # config data for app 01 │ │ │ ├── 📃 package.json # scripts for app 01 │ │ │ ├── 📃 playwright.config.ts # config details for app 01 │ │ └── 📁 app 02 │ │ │ ├── 📁 data │ │ │ │ ├── 📃 page_01.data.json # data for app 02, page 01 │ │ │ │ ├── 📃 page_02.data.json # data for app 02, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.data.json # data for app 02, page n │ │ │ ├── 📁 fixtures │ │ │ │ └── 📃 index.ts # app 02 specific fixtures │ │ │ ├── 📁 locators │ │ │ │ ├── 📃 page_01.locator.ts # locators for app 02, page 01 │ │ │ │ ├── 📃 page_02.locator.ts # locators for app 02, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.locator.ts # locators for app 02, page n │ │ │ ├── 📁 pages │ │ │ │ ├── 📃 page_01.page.ts # functions for app 02, page 01 │ │ │ │ ├── 📃 page_02.page.ts # functions for app 02, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.page.ts # functions for app 02, page n │ │ │ └── 📁 tests │ │ │ │ ├── 📃 page_01.spec.ts # tests for app 02, page 01 │ │ │ │ ├── 📃 page_02.spec.ts # tests for app 02, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.spec.ts # tests for app 02, page n │ │ │ ├── 📃 config.json # config data for app 02 │ │ │ ├── 📃 package.json # scripts for app 02 │ │ │ ├── 📃 playwright.config.ts # config details for app 02 │ │ └── 📁 ... │ │ └── 📁 app n │ │ │ ├── 📁 data │ │ │ │ ├── 📃 page_01.data.json # data for app n, page 01 │ │ │ │ ├── 📃 page_02.data.json # data for app n, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.data.json # data for app n, page n │ │ │ ├── 📁 fixtures │ │ │ │ └── 📃 index.ts # app n specific fixtures │ │ │ ├── 📁 locators │ │ │ │ ├── 📃 page_01.locator.ts # locators for app n, page 01 │ │ │ │ ├── 📃 page_02.locator.ts # locators for app n, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.locator.ts # locators for app n, page n │ │ │ ├── 📁 pages │ │ │ │ ├── 📃 page_01.page.ts # functions for app n, page 01 │ │ │ │ ├── 📃 page_02.page.ts # functions for app n, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.page.ts # functions for app n, page n │ │ │ └── 📁 tests │ │ │ │ ├── 📃 page_01.spec.ts # tests for app n, page 01 │ │ │ │ ├── 📃 page_02.spec.ts # tests for app n, page 02 │ │ │ │ ├── 📃 ... │ │ │ │ ├── 📃 page_n.spec.ts # tests for app n, page n │ │ │ ├── 📃 config.json # config data for app n │ │ │ ├── 📃 package.json # scripts for app n │ │ │ ├── 📃 playwright.config.ts # config details for app n │ └── 📁 utils │ │ ├── 📁 base │ │ │ └── 📁 web │ │ │ │ ├── 📃 actions.ts # actions in web applications │ │ │ │ └── 📃 screenshots.ts # screenshot functions │ │ ├── 📁 functions (utility functions) │ │ ├── 📁 packages (other reusable packages) │ │ └── 📁 reports │ │ │ └── 📃 custom-reporter.ts # custom reporter to pretty print in console ├── 📃 config.init.ts # configuration initializer ├── 📃 global-setup.ts ├── 📃 global-teardown.ts ├── 📃 package.json ├── 📃 playwright.config.ts # global configSo, why is the structure important 🤔 Coz' it gives you the view of the things that you need to add for using this framework for a brand new application. The only problem is to know how to do it sequentially. For example, as soon as you look at the framework structure, you might already understand that you need app_name folder within the src/apps folder within which you would need to create all the sub-folders as shown.The question is which one should I create first and how are these folders linked?Moving on.. First things first. Listed below are the necessary pre-requisites for the framework implementation.Node JS - v18.1.0 or above (what I used while developing) IDE of your choice (VS Code recommended)and... that's it! 💁♂️ - If you want to use different versions of node in different projects, use nvmAlright, now that we have completed the pre-requisites, let’s start with the rest of the implementation 🔰Step # 1Clone the git repo using the below command git clone git@github.com:eric-stanley/playwright-framework.gitand cd into the cloned folderStep # 2Let’s assume that the application under test is named automation-practice Start creating the necessary 📁 and 📃 using the below commands. mkdir src/apps/automation-practice && cd src/apps/automation-practice && mkdir data && mkdir fixtures && mkdir locators && mkdir pages && mkdir tests && touch config.json && touch package.json && touch playwright.config.ts && touch data/home.data.json && touch fixtures/index.ts && touch locators/home.locator.ts && touch pages/home.page.ts && touch tests/home.spec.tsCopy the below code and paste it in src/apps/automation-practice/config.json. This file has the environment specific url's for the AUT (Application Under Test) { "env": { "dev": { "url": "https://magento.softwaretestingboard.com/" }, "test": { "url": "https://magento.softwaretestingboard.com/" }, "uat": { "url": "https://magento.softwaretestingboard.com/" } } }🔔 Assuming that we have the same url for all environments 😏 Copy the below code and paste it in src/apps/automation-practice/package.json. Here we define the commands that we use to trigger the necessary run Note: This is a dependent file and will not run standalone. All dependencies for the framework is part of the main package.json which resides in the parent folder { "name": "automation-practice", "version": "1.0.0", "private": true, "author": "Eric Stanley", "license": "MIT", "scripts": { "test": "APP_NAME=automation-practice NODE_ENV=dev playwright test", "test:debug": "APP_NAME=automation-practice NODE_ENV=dev PWDEBUG=1 playwright test", "report": "npx playwright show-report reports/playwright-report", "allure": "npx allure generate reports/allure/allure-result -o reports/allure/allure-report --clean && npx allure open reports/allure/allure-report" } }🔔 Change the author to your name Copy the below code and paste it in src/apps/automation-practice/playwright.config.ts. This file has the app specific playwright config. import { PlaywrightTestConfig, devices } from "@playwright/test";const config: PlaywrightTestConfig = { testDir: "tests", testMatch: "tests/*.spec.ts", timeout: 30 * 1000, retries: 3, workers: 3, globalSetup: require.resolve("@home/global-setup"), globalTeardown: require.resolve("@home/global-teardown"), expect: { timeout: 20000, }, use: { headless: true, actionTimeout: 0, trace: "retain-on-failure", ignoreHTTPSErrors: true, video: "on-first-retry", screenshot: "only-on-failure", acceptDownloads: true, colorScheme: "dark", launchOptions: { slowMo: 500, }, }, reporter: [ ["list"], [ "json", { outputFile: "reports/json-reports/json-report.json", }, ], [ "html", { outputFolder: "reports/playwright-report/", open: "never", }, ], [ "allure-playwright", { outputFolder: "reports/allure/allure-result/", open: "never", }, ], ], projects: [ { name: "chromium", use: { ...devices["Desktop Chrome"] }, }, { name: "firefox", use: { ...devices["Desktop Firefox"] }, }, { name: "webkit", use: { ...devices["Desktop Safari"] }, }, ], };export default config;Now that we have completed the basic setup, let’s move on to step # 3Step # 3Let’s start with writing a basic test for verifying if the home page url contains a specific text and title equals a specific text Starting with the data first. Add the below data in src/apps/automation-practice/data/home.data.json { "urlContains": "softwaretestingboard", "title": "Home Page - Magento eCommerce - website to practice selenium | demo website for automation testing | selenium practice sites | selenium demo sites | best website to practice selenium automation | automation practice sites Magento Commerce - website to practice selenium | demo website for automation testing | selenium practice sites" }Now that we have the data in place, lets start writing the functions for the test. Add the below code to src/apps/automation-practice/pages/home.page.ts import type { Page, TestInfo } from "@playwright/test"; import { test, expect } from "../fixtures"; import * as data from "../data/home.data.json"; import * as actions from "@utils/base/web/actions";export default class HomePage { constructor(public page: Page, public workerInfo: TestInfo) {} async navigateToAutomationPractice() { await actions.navigateTo(this.page, process.env.URL, this.workerInfo); const url = this.page.url(); await test.step( this.workerInfo.project.name + ": Check if URL contains " + data.urlContains, async () => expect(url).toContain(data.urlContains) ); } async verifyPageTitle() { await actions.verifyPageTitle(this.page, data.title, this.workerInfo); } }At this point, you will get an error with the fixtures import line stating that, fixtures/index.ts is not a module. This is fine. We are going to tackle this next 😉 But before that, let's take a moment to look at the code in home.page.ts. Basically, I have added two functions in this class; one for navigating to the home page navigateToAutomationPractice() and the other one to verify the title of the page verifyPageTitle(). The actions is a consolidated list of all actions (or atleast most of the actions) that you could possibly perform in a web page, since we will be using these actions in almost all of our pages, it's only logical to have this as a separate utility! Let’s tackle the fixtures error now. Add the below code in src/apps/automation-practice/fixtures/index.ts import { test as baseTest } from "@playwright/test"; import CommonPage from "@common/pages/common.page"; import HomePage from "../pages/home.page";type pages = { commonPage: CommonPage; homePage: HomePage; };const testPages = baseTest.extend<pages>({ commonPage: async ({ page }, use, workerInfo) => { await use(new CommonPage(page, workerInfo)); }, homePage: async ({ page }, use, workerInfo) => { await use(new HomePage(page, workerInfo)); }, });export const test = testPages; export const expect = testPages.expect; export const describe = testPages.describe;What we do here is basically extending the test object in @playwright/test to add all pages in our application, so that when we start writing our tests, we will be able to easily pull the page objects and its associated functions without creating a new object everytime when we need to access the home.page.ts which might inturn cause a lot of duplication in code. In other words, every time we access the test object from @playwright/test, it automatically injects all the app specific pages in it. Let’s see how it happens next Add the below code in src/apps/automation-practice/tests/home.spec.ts import { test, describe } from "../fixtures";describe("Home", () => { test("Verify home page url and title", async ({ homePage }) => { await homePage.navigateToAutomationPractice(); await homePage.verifyPageTitle(); }); });As you can see the second argument in the test object takes in a function and since we have already extended the homePage object within the test object, we are able to access it with in the function And..... that's it ⏰ Now, before we run the test, there is one last place where we need to update few things which is basically the script object in package.json which is present in the parent directory.Remember, this is not the package.json that we edited in step # 2. This is the one that is present in your parent (root) directoryAdd the below code in the scripts section in package.json file "test:automation-practice": "yarn workspace automation-practice test", "test:debug:automation-practice": "yarn workspace automation-practice test:debug", "report:automation-practice": "yarn workspace automation-practice report", "allure:automation-practice": "yarn workspace automation-practice allure"Once you are done with editing the package.json file in your root directory, you package.json file would look something like below { "name": "playwright-hands-on", "version": "1.0.0", "private": true, "description": "", "workspaces": ["src/apps/*"], "scripts": { "test": "yarn workspace ui-testing-playground test", "test:debug": "yarn workspace ui-testing-playground test:debug", "report": "yarn workspace ui-testing-playground report", "allure": "yarn workspace ui-testing-playground allure", "test:ui-testing-playground": "yarn workspace ui-testing-playground test", "test:debug:ui-testing-playground": "yarn workspace ui-testing-playground test:debug", "report:ui-testing-playground": "yarn workspace ui-testing-playground report", "allure:ui-testing-playground": "yarn workspace ui-testing-playground allure", "test:automation-practice": "yarn workspace automation-practice test", "test:debug:automation-practice": "yarn workspace automation-practice test:debug", "report:automation-practice": "yarn workspace automation-practice report", "allure:automation-practice": "yarn workspace automation-practice allure" }, "author": "Eric Stanley", "license": "MIT", "devDependencies": { "@playwright/test": "^1.25.2", "@types/adm-zip": "^0.5.0", "adm-zip": "^0.5.9", "allure-commandline": "^2.18.1", "allure-playwright": "^2.0.0-beta.19", "colors": "^1.4.0", "playwright": "^1.25.2", "ts-node": "^10.9.1", "typescript": "^4.8.3" } }Step # 4Time to test If you are running the project for the first time run the yarn command from your parent folder to install all dependencies. Once you are done with installing the dependencies, run the below command yarn test:automation-practiceIf you have done everything right, you might probably see something like belowYou might or might not get the Slow test file warning. You can play around with it by changing the timeout value in playwright.config.ts in src/apps/automation-practice folder 🙋 Now, does that mean that we are done?Yep!I told you that this post would be a long one and we have covered a lotta ground until now, but why do we have the home.locator.ts file in the locators folder. And how do we compare screenshots 🤔 Like I said, this could take some time, but at the same time, a lot has been already done. See you in the next post with implementing more features 🥏 Feel free to add your thoughts and comments in the comments section and I will try to address those in time ⏰

Eric Stanley- 06 Sep, 2020
Short circuit in javascript
Short circuit is an interesting concept in JavaScript where we make JavaScript to evaluate a typically unorthodox condition to human eye but make total sense to JavaScript typing engine So what do I mean my unorthodox anyway? Let’s take an if statement for example if (condition) { // do something if true } else { // do something else }If you look at the above statement from a layman perspective, he/she could still understand what the code does just by knowing a little english!! What that also means is that the code you see is as per the books and that’s how anyone teaches to code The above code can also be written using ternary operators like below (condition) ? // do something if true : // do something if falseHowever, the reason why ternary operator code is not traditional is because it does not have any keywords in it. Anyone could still understand the above syntax, but when it’s implemented in actual code like (a === b) ? x = y : x = zIt’s kinda hard for a newbie to understand what the code actually means or how it works. More about ternary operators hereNow, why am I taking about if statements and ternary operators when the heading says Short circuit in JavaScript!It’s because though there is no performance improvement by using ternary operators instead of traditional if else, it’s a little less to write. And if that makes you insane, get ready for obsession Short circuiting in JavaScript is all about how you play around logical operators with falsy and truthy values Before we move any further, let’s understand what falsy and truthy values areAny value that is considered false when expressed in boolean context is falsy. The value that I’m referring here could be anything. It could be a variable, array, object, condition, etc.Ok, so a boolean variable can be assigned a value of false and it becomes falsy. But how can I assign a value of false to an array. An array can be empty or undefined but definitely not false. That would make no sense! Good news is, JavaScript has some predefined values that are considered falsy The falsy values in JavaScript arethe number 0 the BigInt 0n the keyword null the keyword undefined the boolean false the number NaN the empty string "" (equivalent to '')The above values evaluate to false when coerced by JavaScript’s typing engine into a boolean value, but they are not necessarily equal to each other. And what are truthy values then? Everything else except falsy is truthy. Simple ❇️ Fun time!! Let’s start with an example again. Consider the following if statement if (condition) { // do something if true }If we use the ternary expression, the above if statement can be written as condition ? // do something if true : nullIf you notice closely, you might see that there is an unnecessary else condition in the ternary expression which basically does nothing. The problem is you can’t neglect it. A ternary expression should always have something to do for both true and false conditions which makes ternary expression not an optimal choice when there’s only if and no else Now, how can we rewrite this to make it smaller Time to get obsessed (condition) && // do something if trueLike I said, it’s basically how we play around with logical operators Before we dive into how the code works, it’s necessary understand how logical operators work. It works from left to right and short circuits What do I mean by short circuit here? When JavaScript evaluates an AND (&&) expression, if the first operand is false, JavaScript will short circuit and will not even look at what’s next in lineRemember, the logical AND returns true only if all conditions match. In other words, in a given sequence of conditions with logical AND operators will complete its execution successfully only if all conditions are true. The moment any of the condition is false, it just doesn’t matter whether or not the remaining conditions are true. The end result is gonna be falseSimply put, all conditions that comes after the false condition is not gonna affect the result. And if the result is clear even before evaluating all the conditions, it short circuits!It’s the same principle, JavaScript just short circuits once it encounters a false value and just ignores the remaining conditions and returns to the next line of code Before I close let’s just see a real example with logical AND (&&) and logical OR (||) let a, b, xa = 1 // b = undefined x = 'I am the default value'console.log(a && x) // prints 'I am the default value', since a is true console.log(b && x) // prints undefined, since b is false (short circuits and anything after false is not executed)console.log(a || x) // prints 1, since a is true (short circuits and anything after true is not executed) console.log(b || x) // prints 'I am the default value', since b is falseThat’s my best explanation of what short circuit is in JavaScript After all, no one said a bread board logic would NOT be helpful someday in the programming world 🙂

Password Management
Managing passwords is often a challenging task unless you have a eidetic memory or lazy enough to click on forget username/password. I believe the neither of those is gonna end up reading this post and trust me, you are not one of ‘em either! So, when it comes to managing passwords, the first thing that comes to our mind is the best password management app in the app store or play store. Apparently, when we search it, we will end up in getting to know about the app that is listed in most of the sites and most reviews etc. So obviously, any person would not be needing to ask some security expert to decide on what app to choose. Now, am I a security expert? Hell no! I am not against the apps that are listed as the best in any point in time, however I am not someone who believes that the news is always true. Infact, the truth is what the media say it is. And this applies to websites as well. Now, before we get into the actual password management details, lets split things up into discrete pieces, so that we could better understand the need for password management.Why do we need to protect our passwords? Coz’ if someone else gets access to our password, they might tamper with our identityLet’s call this someone ‘X’Does X really need your password? Unless, you are a friend/enemy of X, X wouldn’tDo I know X personally? Well, most probably no, coz’ X is a company most of the times and X being a person seldom happensAs you see, you cannot be a possible victim unless its X’s personal vendetta or you are on your way to becoming a celebrity/millionaire Therefore, its unlikely for X to target an individual and lot likely to target a company which has strong user base (One reason why big companies are falling victim to attacks by X). Also, as all of your credentials is stored in one single infrastructure, though the data is encrypted, you still are a victim as you have given all your data to X. Its just a matter of time before X finds a way to decrypt Well, if that’s the case, what else can we do. Do I mean that there is no actual protection? YES!But we can definitely work on minimizing the risk of saving all our details under one single infrastructure and maybe placing partial data in a place which is secure and the remaining in an unsecured location. The reason I say unsecured is coz’ this is where the protection actually happens. The last thing they would search is their own backyard. No wants to steal data that is open to everyone. That ain’t stealing anyways! The phrase That is where they least expect to hit ‘em from just doesn’t apply for X just coz’ there are lot of other better places for them to hit and they would never know if that’s worth it If this theory sounds good to you, let's start practicals now. There is an existing password manager which already fits the above theory. You can find the website here Considering the above theory, you can safely assume that the app needs some basic understanding of the belowHow to create a github repository (private repo recommended) How to generate a PGP key pair (online generator here)*** Recommended optionsNote: The longer the passphrase, the more secure you password is and its ok to have the expires option set to NeverOnce you are done with the above 2 steps, it's time to install the app from the Compatible Clients section in https://www.passwordstore.org/ site After installation you would be required to enter the git repo and PGP key pair details before using the app Once repo and key details are entered you are good to go!Just to clear things about how this app ties to our theory, we need to understand a little more about how this app works. The repo you create is basically the database where you store your encrypted passwords. That would mean, each user has separate database (git repo) and it is in github (The world’s largest host of source code). Now, the password that you encrypt needs the key and the passphrase in order to be decoded; which again you have it in your local file system. In other words, you have the keys and passphrase in your app data folder and not in any server. As you see, you have now separated the key (PGP file) and the lock (git repo) and the only possible way to get access to your passwords is to get access to your key, passphrase and github repo! That would mean, hacking any one of these has no impact whatsoever!As a side note, its better to have a password hint in the password section instead of the actual password in the appThat said, this obviously is not an easy password management practice, but once setup its worth more than the money you spend on any subscription based or paid password management service. And the best part; you can have as many fields you want for any website/app by adding new keys as key value pairs Now, how do I know if this is the best/right way to manage passwords?Well, I don’t. It’s just my way 🙂

Eric Stanley- 30 Dec, 2019
JavaScript: Array Manipulation
JavaScript offers different ways to manipulate arrays. However, there are methods that changes the original array and other methods that don’t. The methods that changes original array is called MUTATION. Let’s take a look at most common methods to manipulate arrays in JavaScript Now, that we know that there are methods that mutates the original array, it’s considered best practice to assign the array to const, if you know that the array that you use is not going to get mutated. It’s wise to use let otherwise. It is not a mandate that you need to use const to declare an array that will not be mutated, however, it’s easy for your colleague to understand that the array which is declared as const is not going to get changed anywhere in the code; which is why it’s considered best practice As usual, if you wanna try the examples in this post, I recommend codepen.io, but you are free to make your own choice. The most common interactions that we usually have with arrays areAdd item to array Remove item from array Update and item in the arrayAll the above mentioned actions can be done by both mutating and non-mutating methods. Instead of explaining each of the methods subjectively, I felt it would be better understood with a table. Here we go! testArray: [a, b, c, d, e, f, g, h, i];Code Original Array Processed Array Returned Val Is Mutated Action MethodtestArray.push('j') [a,b,c,d,e,f,g,h,i] [a,b,c,d,e,f,g,h,i,j] 10 true add push()testArray.unshift('z') [a,b,c,d,e,f,g,h,i,j] [z,a,b,c,d,e,f,g,h,i,j] 11 true add unshift()testArray.concat('k') [z,a,b,c,d,e,f,g,h,i,j] [z,a,b,c,d,e,f,g,h,i,j] [z,a,b,c,d,e,f,g,h,i,j,k] false add concat()['y', ...testArray, 'l'] [z,a,b,c,d,e,f,g,h,i,j] [z,a,b,c,d,e,f,g,h,i,j] [y,z,a,b,c,d,e,f,g,h,i,j,l] false add ...testArray.pop() [z,a,b,c,d,e,f,g,h,i,j] [z,a,b,c,d,e,f,g,h,i] j true remove pop()testArray.shift() [z,a,b,c,d,e,f,g,h,i] [a,b,c,d,e,f,g,h,i] z true remove shift()testArray.splice(0, 2) [a,b,c,d,e,f,g,h,i] [c,d,e,f,g,h,i] [a,b] true remove splice()testArray.filter(a => a!== 'c') [c,d,e,f,g,h,i] [c,d,e,f,g,h,i] [d,e,f,g,h,i] false remove filter()testArray.slice(1, 6) [c,d,e,f,g,h,i] [c,d,e,f,g,h,i] [d,e,f,g,h] false remove slice()testArray.slice(2) [c,d,e,f,g,h,i] [c,d,e,f,g,h,i] [e,f,g,h,i] false remove slice()testArray.splice(2, 1,30, 31) [c,d,e,f,g,h,i] [c,d,30,31,f,g,h,i] [e] true update splice()testArray.map(x => x ==='d' ? 29 : x) [c,d,30,31,f,g,h,i] [c,d,30,31,f,g,h,i] [c,29,30,31,f,g,h,i] false update map()I hope the above table is self-explanatory, however if you need to check the values of the testArray with real code, feel free to visit programmatic output where the exact same table is derived programmatically. Codepen pin link

Eric Stanley- 25 Nov, 2019
Cookie Policy
Ever wondered why do websites have no decline option in their cookie policy popup? Well, lets’ see. Today, almost all sites in the internet uses cookies that is stored temporarily in the system cache to ease authentication of the same user in the same system. I’m talking about well-established sites that makes some use of the information in your local machine (THE COOKIE!). Why do I need it? As per GDPR, every website that tracks their visitors should have the visitors consent to use their data to better manage what they need. So if you are tracking your website users and making decisions based on their user data, then ‘YES’, you have to force the user to accept your cookie policy. Do I need it? Before we get into the fun part, we gotta understand what this cookie policy can do. Let’s say you own a blogging portal with ‘Disqus’ comment system enabled. Obviously, any visitor need to have a ‘Disqus’ account in order to comment. This means, like it or not ‘Disqus’ can track your visitors on which sites they visit and which site they comment and maybe manipulate your data based on their need. Now, let’s get into the fun part. As long as you plan to use your visitor’s data and manipulate something from it, you gotta have the cookie policy in your site. However, what do you think you can do with your visitor’s data? As soon as that question is asked, we start to think big! Maybe we can find users locations. “Ok, then what?” If you are just planning or started a blog for yourself like me, all we have is our petty subscription list, which is a list of email ids’ that will be almost empty for atleast couple of months! What can possibly be done with that except sending emails about new posts, which again seldom occurs? Therefore, my view of adding a cookie policy is, if you are just starting a blog; just make sure that you are not adding any tracking 3rd party code that tracks your blogs visitor. That means, in case of WordPress websites, the plug-ins that you use in your site may need you to register in order to use it, but not for your visitors. That is it. You have a long way to go before you even think about adding the cookie policy. Just focus on adding new and useful posts. After all, who wants to accept a policy that has no choices?

Eric Stanley- 15 Nov, 2019
How to start blogging
Now this being an obscure topic, I will try to be as different as possible. First things first, you guessed it right. Bluehost. Every post that I found about how to start a blog has section to create Bluehost account and use their service. I am not going to make any suggestions here, but I would say make your own research before buying a hosting space. Most of us tend to believe that the service that the product owner provides is directly proportional to the service that they provide and most of the times, it is true. Let’s see an example here. Service provider X bills $2.00 per month and service provider Y bills $1.60 per month. Now without knowing anything about either X or Y, if someone asks which one is better (without considering the cost), we would say X is better. Now, the outcome of the above scenario is either X might actually be better or maybe not. The point is, you are going to create a blogging portal for yourself or for your niche and you are not going to build a website like google. That means during the initial days, all you need is a single digit simultaneous user-handling server, which you will be hitting all alone. And, by the time you reach a significant user base, you will be matured enough to handle hosting changes. We don’t have to overthink here. Some would prefer cheap and some would prefer quality. I would let you decide on that. Though, this site is not a WordPress site, I would recommend non-technical users to go-ahead with any hosting provided which installs WordPress. Now, one of the mistakes that I did was looking free resources everywhere, until I realized that I would lose my interest as long as something is free. Coz’ as long as you know that something is free and you can get it anytime you wanted and you have nothing to lose, chances of losing interest are more likely to come true. What I’m trying to say is, just buy a paid WordPress theme that you like. Don’t go for free themes. Now, some people might argue that the above statement (or everything) is not true and I agree to that. I have seen sites (sub-domains) in blogspot.com and wordpress.com having more visitors than individually/business owned sites. I gotta say, “They are great bloggers”. This post is just for the ones that are trying to do something good and no intent to become great! Now, if you are still reading this. It’s time for you to start writing.

Eric Stanley- 01 Nov, 2019
How to stay a blogger
Staying a blogger is always gonna be hard business. After revamping my blog site, I reviewed most if the interesting and well-established personal blogger sites and guess what, they are not staying a blogger consistently. It’s quite obvious that once you plan to start a blog, you put some good efforts into it and it’s no surprise. I have seen blogs where there were close to 80 posts in a month 10 years ago and hardy any posts in a month now. And I say that is no accident. It’s just the way life goes. Everyone has other work to do apart from blogging unless you earn quite enough from your blog posts. So, my first point about how to stay a blogger is plan not to. Yes. You read it right. Coz’ if you are creating your own blog, you are more likely to lose interest in due time and that’s totally human. That’s why I plan to create posts only when I have time and spend enough time to create one before publishing. That way I know that I am doing this only coz’ I’m interested in writing and not expecting anything more. Now, there is always a different opinion from different people and I respect that. If you think you can plan your life so perfectly, that even after a decade your plan still stays the same, I probably prefer anyone like that, not reading this blog! Having said that, my primary objective now with this post of mine is basically NOT to prove a point and that’s the way the cookie crumbles 🙂

Eric Stanley- 12 Oct, 2019
Binary Search
Before we get into the syntax and logic of binary search algorithm, let’s ask ourselves this question. Why do we need binary search at all in the first place? To understand, let’s work with an example here. Let’s say you were given a name in a letter pad (say ‘Michael’) and you were asked to find that person from a group of 50 people who are standing by name order i.e., Adam stands first, then Alex, then Bob and goes on. You get the idea. Now, what you do is, pick the 25th person and ask his/her name. Let’s say the person’s name is ‘Monica’. Now you know that ‘Michael’ is somewhere before ‘Monica’ as everyone is standing in ascending order. The reason I picked the 25th person, is coz’ picking that person would give me the max reduction. In the sense, I can ignore the other 25 people after ‘Monica’, since; I know that ‘Michael’ cannot come after ‘Monica’. The idea is filtering 50% of the wrong choices in every question you ask, will give you the fastest route to the destination. To make it clearer, let’s say I pick a random number (say 35) instead of picking the 25th person. I ask the 35th person, what his/her name is? Now there are two possible outcomes. Either his/her name can be ‘Stuart’ or ‘Henry’. Now, you have a 50 percent chance that you might get either one of these names. If the person says ‘Henry’ then you are lucky, coz’ you only need to filter remaining 15 people to find out your match, but guess what, what if the person’s name is ‘Stuart’, you just got burned here! In other words, instead of filtering from your best bet number, which is 25, now you need to filter from 35. Hope you get the reason why you need to filter by half every time to find the quickest way to find your match. If all the names in the world are written down together in order and you want to search for the position of a specific name, binary search will accomplish this in a maximum of 35 iterations, which means with asking 35 questions, you will be able to find the person that you are looking for. Isn’t that cool! Hence, always try to order your array or collection in some way and make sure to index it i.e., if you are adding a row in your excel spreadsheet which you know that the records are gonna increase in the course of time, make sure to add a serial number to each row, so that you can order by ascending/descending anytime to sort the list and, once the list is sorted, perform the binary search to find the record you need. So, to answer the question ‘why’, binary search algorithm is one of the fastest way to find a random number in a set of indexed numbers, instead of searching the numbers sequentially. Now that’s why! Alright, funz over. Let’s get to work now. Below is the program to implement binary search in VB Script Dim testarr(100000) Dim n, i, resn = 5643For i = 1 To 100000 testarr(i) = i Nextres = CStr(binser(testarr, n)) Wscript.echo resFunction binser(arr, tar) Dim low, high low = LBound(arr) high = UBound(arr) iter = 0 Do While low <= high i = Round((low + high) / 2) If tar = arr(i) Then binser = True Wscript.echo iter Exit Do ElseIf tar < arr(i) Then high = i - 1 Else low = i + 1 End If iter = iter + 1 Loop If Not binser Then binser = False End IfEnd FunctionNote: Binary search works only with sorted arrays, it just won’t work in case of unsorted arrays. Imagine the people are standing in unsorted order in the above example, in which case, you just got double burned! And the odds of finding a person (out of 50) is you gotta ask atmost 49 questions to find the person who you are looking for. You gotta be really lucky otherwise!