Skip to content

fabremx/crafting-frontend-exercices

Repository files navigation

📝 Crafting Front-End Formation - Cheat sheet


Summary

  1. Creating Web Component
    1.1 How to create a web component ?
    1.2 How to import component in file ?
    1.3 How to set a web component attribute ?
    1.4 How to create a custom event and dispatch it ? 1.5 How to listen and handle an event ?

  2. Testing Web component
    2.1 How to load my web component ?
    2.2 How to access to the DOM of my web component ?
    2.3 How to create a story with controls
    2.4 How to do snapshot test with Jest ?
    2.5 How to create a custom event and dispatch it ?
    2.6 How to create a stub of a function ?
    2.7 How to set attributes to a web component ?

  3. Utilities & Cheat sheet
    3.1 DOM selectors cheat sheet
    3.2 Jest cheat sheet
    3.3 Functions
    3.4 Playwrigth cheat sheet

  4. Exercices Helpers
    4.1 Create a Footer - Exercice n°2
    4.2 Testing Betting-list - Exercice n°4


📗 1. Creating Web component

1.1 How to create a web component ?

import { CustomHTMLElement } from '../../utils'

/* Create template */
const template = document.createElement('template');
function createTemplate(name: string): string {
    return `
        <div>Hello ${name} !</div>
    `
}
export class MyComponent extends CustomHTMLElement {
     constructor() {
        super()

        /* Attach template to shadow DOM */
        this.attachShadow({ mode: 'open' })
            .appendChild(template.content.cloneNode(true))
    }

    connectedCallback() {
        /* Create template with variable on the first rendering */
        const name = 'Maxime'
        const newTemplate = createTemplate(name)
        this.renderComponent(newTemplate)
    }
}

/* Define tag with 'arl' prefix */
customElements.define('arl-my-component', MyComponent);

You can call now your component with the tag <arl-my-component></arl-my-component>

1.2 How to import component in file ?

In order to import a component "Header" in App.ts for example use

import './src/components/header/header'

1.3 How to set a web component attribute ?

<!-- /!\ attributes must be in lowercase --> 
<arl-footer is-user-connected="false"></arl-footer>
class MyComponent extends CustomHTMLElement {
    ...

     static get observedAttributes() {
        return ['is-user-connected']
    }

    attributeChangedCallback(attributeName: string, _oldValue: string, newValue: string) {
        // catch any attributes changes
    }
}

1.4 How to create a custom event and dispatch it ?

const objectToPass = { key: 'value' }
const event = new CustomEvent('eventName', { detail: objectToPass }) /* 'detail' is mandatory in customEvent */

window.dispatchEvent(event)

1.5 How to listen and handle an event ?

window.addEventListener('eventName', callback())

📙 2. Testing Web component

2.1 How to load my web component ?

class MyComponent extends CustomHTMLElement {}

const myComponent: HTMLElement = render(MyComponent)

2.2 How to access to the DOM of my web component ?

// myComponent is a HTMLElement you can access to the DOM with classical js **methods**
myComponent.shadowRoot.querySelector(...)

2.3 How to create a story with controls ?

import { StorybookControls } from '../../models'
import './footer'

export default {
    title: 'Components/Footer',
    argTypes: {
        isUserConnected: {
            control: 'boolean',
            defaultValue: false
        },
    }
}

type ArgTypes = {
    isUserConnected: StorybookControls,
}

export const Default = (argTypes: ArgTypes) => `<arl-footer is-user-connected="${argTypes.isUserConnected}"></arl-footer>`

2.4 How to do snapshot test with Jest ?

expect(...).toMatchSnapshot();

2.5 How to spy parameters sent (dispatchEvent) ?

const spyDispatchEvent = jest.spyOn(window, 'dispatchEvent');
const expectedParameters = (spyDispatchEvent.mock.calls[nthCall][nthParameter] as CustomEvent).detail /* nthCall: represent the nth call that we want to watch, nthParameter represent the nth parameter sent that we want to watch */
expect(expectedBetChoice).toEqual({ ... })

2.6 How to create a stub of a function ?

const stub = { key: 'value' }

jest.mock('../../services', () => ({
  fetchGameOdds: jest.fn().mockResolvedValue(stub)
}))

2.7 How to set attribute to a web component ?

const objectToPass = { key: 'value' }
const myComponent: HTMLElement = render(MyComponent)

myComponent.setAttribute('my-prop-key', JSON.stringify(objectToPass))

📕 3. Utilities & Cheat sheet

3.1 DOM selectors cheat sheet

querySelectorAll
/* Return an array of requested DOM elements */
myComponent.querySelectorAll(' CSS selectors ')
querySelector
/* Return the requested DOM element */
myComponent.querySelector(' CSS selectors ')
contains
/* Return true/false if class exists or not in requested element  */
myComponent.classList.contains(' class name')
click
/* Simulate a click */
myComponent.click()

3.2 Jest cheat sheet

toBeTruthy
/* Check if value exists or is true */
expect(value).toBeTruthy()
toBeFalsy
/* Check if value does NOT exist or is false */
expect(value).toBeFalsy()
toEqual
/* Check equality with object/array */
expect(value).toEqual(expectedValue)
toBe
/* Check equality with literal type */
expect(value).toBe(expectedValue) 
toContain
/* Check if value contains a expected value */
expect(value).toContain(expectedValue) 
toHaveBeenCalled
/* Check if method have been called (true / false) */
expect(method).toHaveBeenCalled(expectedValue) 
toMatchSnapshot
/* Create or check validity of snapshot */
expect(...).toMatchSnapshot() 

3.3 Functions in utils/webComponent.ts

render
/* Instanciate a component and launch 'connectedCallback()' method if exists */
const myComponent: HTMLElement = render(MyComponent)
stringify
/* Stringify any type of variable in order to pass it as a prop */
myComponent.setAttribute('key-attribute', stringify(object))
parse
/* Parse any stringified attribute value in order to manipulate it */
attributeChangedCallback(name: string, _oldValue: string, newValue: string) {
    const parsedValue = parse(newValue)
}

3.4 Playwrigth cheat sheet

const browser: Browser = await chromium.launch({
    headless: true,
    slowMo: 0,
    devtools: false
})

const context: BrowserContext = await browser.newContext()
const page: Page = await context.newPage()

await myComponent.isBlockDisplayed('tag or CSS selectors')
await input.type('100')
await input.press('Backspace')
await myComponent.getSummaryContent()

📘 4. Exercices Helpers

4.1 Create a Footer - Exercice n°2

Update template depending on the recieved attributes.

import { CustomHTMLElement } from '../../utils'

function createTemplate(text: string): string {
    return `
        <footer>
            <h3>Besoin d'aide ?</h3>
            <p>${text}</p>
        </footer>
    `
}

export class Footer extends CustomHTMLElement {
    constructor() {
        ...
        this.render()
    }


    static get observedAttributes() {
        return ['is-user-connected']
    }

    attributeChangedCallback(attributeName: string, _oldValue: string, newValue: string) {
        if (attributeName !== 'is-user-connected') {
            return
        }

        this.render(newValue)
    }

    render(isUserConnected?: string) {
        const footerText = (isUserConnected === 'true')
            ? 'Contact | Plan | Deconnexion'
            : 'Contact | Plan | Connexion'

        const newTemplate = createTemplate(footerText)
        this.renderComponent(newTemplate)
    }
}

4.2 Testing Betting-list - Exercice n°4

Display a list of game odds using component Betting Item.

function createTemplate(gameOddsList: GameOdds[]) {
  return `
    <div class="betting-list">
        <h3>Liste des paris - Football</h3>
        ${gameOddsList
      .map((gameOdds: GameOdds) => `<arl-betting-item game-odds='${JSON.stringify(gameOdds)}'></arl-betting-item>`)
      .join('')
    }
    </div>
  `
}

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •