1

So im pretty much used to always using classes when writing automation code (Using the Page object Model). However i've came across some PoM/Component sample code that im not really used to seeing. For example this header.ts file is not what I am used to seeing:

import { Page, expect } from "@playwright/test";

export function Header(page: Page) {
  const self = page.locator('header');

  const input = self.getByPlaceholder('What needs to be done?');
  const toggleAllButton = page.getByLabel('Mark all as complete');

  const completeAll = () => toggleAllButton.check();
  const uncompleteAll = () => toggleAllButton.uncheck();
   
  const addTodo = async (text: string) => {
    await input.fill(text);
    await input.press('Enter');
  }; 

  return {
    addTodo,
    completeAll,
    uncompleteAll,
    expect: () => ({
      ...expect(self),
      toAllowUncompleteAll: (allow = true) => expect(toggleAllButton).toBeChecked({ checked: allow }),
      toHaveEmptyInput: () => expect(input).toBeEmpty()
    })
  };
} 

Now this is using Playwright specifically, but the object/component model is similar. In classes you don't typically "return" anything, but here they are returning all the functions to be used elsewhere.

I guess my main question is:

  1. Why do we have to return the functions within here as opposed to a class once you create the instance object we don't have to return anything.
  2. Is there really any advantage to doing it this way vs a class? (Feels messier?)
  3. I don't under the ...expect(self) and what that is doing. To be honest why is self used here anyways? (Im not familiar with how self works in functions)
4
  • 1
    self is just a variable. (Well, a constant, but it's just a name.) Commented Aug 28, 2023 at 19:20
  • 2
    This is a style that was often used before ES6 classes. Commented Aug 28, 2023 at 19:20
  • Well… there's no class here. What you're looking at is a function. A function that returns an object. Commented Aug 29, 2023 at 3:06
  • The code you posted is returning an object with the functions, not just the functions. {} is shorthand for "object". Commented Aug 29, 2023 at 11:16

1 Answer 1

2

It's the Revealing Module Design Pattern.

By using this you can simply define all functions and variables in the private scope and return an anonymous object with pointers to the private functionality to expose to other code areas where required utilizing closures.

This is a very clean way of specifying the public functions that you want to expose to the outside world. I think , the biggest advantage of revealing module pattern is that provides cleaner code structure.

The revealing module pattern is used to provide an abstraction over private implementations by providing public APIs. I think more or less we achieve the same thing using classes.

Simple Code Example:

// JavaScript Revealing Module Pattern
const Person = (function () {
  // Private Properties
  let name;
  let lastName;

  function publicSetName(_name, _lastName) {
    name = _name;
    lastName = _lastName;
  }

  function publicGetName() { return `${name} ${lastName}` }

  /**
   * Reveal public pointers to 
   * private functions and properties
   */
  return {
    setName: publicSetName,
    getName: publicGetName
  }
})();

const client = Person;

client.setName('Vishu', 'A.');
console.log(client.getName()); // Vishu A.
// The name property is not accessible.
console.log(client.name); // undefined

This was used to emulate the concept of classes earlier but including public/private properties and methods, protecting certain parts from the global scope by the use of closures.

In my personal opinion , I find it more cleaner solution than classes.

For further Reading: https://javascript.plainenglish.io/module-design-pattern-vs-classes-in-javascript-45568e74ad2a

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you moderators @deceze for pointing out my mistake in the last answer. It took me whole night to explore the concept fully (and all the related concepts around it with trade-offs) but it was the rewarding experience in the end. I learnt something.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.