Uno degli approcci più comuni allo sviluppo di applicazioni moderne è quello di creare una serie di componenti minimali, isolati e riutilizzabili in tutta la codebase dell’applicazione. Che siano sviluppati in Angular, in React, come Web Component o con qualsiasi altro framework, essi renderanno più agevole lo sviluppo e consentiranno di concentrarsi sugli aspetti architetturali più importanti del progetto.
E ciò può essere replicato anche su più progetti, facendo risparmiare più volte il tempo risparmiato utilizzando uno UI kit sviluppato in precedenza. Soprattutto in questo caso – ma non esclusivamente ad esso – fornire una documentazione completa e visuale dei componenti è un punto critico per una corretta condivisione e utilizzo della libreria.
Storybook
Uno degli strumenti più diffusi per questo obiettivo è senza dubbio Storybook. Nato come semplice showcase di componenti sviluppati con React, col tempo si è arricchito con il supporto ad altri framework (Angular, Vue, Web Components, più altri grazie alla community) e funzionalità.
Il concetto alla base di Storybook, in ogni caso, è sempre uguale: mostrare in isolamento i componenti del nostro progetto e dare modo di poterne manipolare i valori in input per osservarne gli effetti. Il classico modo di affrontare il compito è quello di individuare i vari casi d’uso di ogni componente, ognuno dei quali andrà a costituire una storia (da cui il nome della libreria).
Ad esempio, un componente “pulsante” potrà avere – a seconda dello scopo d’uso – un colore d’accento o uno secondario; dimensioni maggiori o minori; avrà un’icona, o sarà disabilitato, e così via.
Controlli
Oltre alla mera rappresentazione visuale dei componenti, Storybook offre nativamente un sistema di rappresentazione delle variabili che possono influenzare un componente, consentendo eventualmente all’utente di modificare al volo tali valori. Questi meccanismi vengono detti controlli (o knobs nella letteratura più obsoleta su Storybook).
Ogni proprietà e attributo del componente esposto come API pubblica dovrebbe avere rappresentazione tra i controlli, e ogni storia dovrebbe essere definita da valori dei controlli preimpostati, lasciando sempre la possibilità all’utente di modificare a piacimento i valori.
Azioni
Oltre al feedback visivo, è possibile tracciare gli eventi che vengono generati dall’interazione diretta o indiretta dell’utente con il componente. Che si tratti di chiamate al backend, eventi generati o di azioni di store, questi possono essere visualizzati nella sezione “Actions”.
Pagine custom
Per completare l’istanza di Storybook come contenitore universale di documentazione per una libreria di componenti, è possibile creare delle pagine “custom” che possono semplicemente mostrare del contenuto libero. In questo modo, è possibile creare pagine per:
- illustrare i principi del design system;
- creare un elenco di proprietà di base;
- inserire esempi concreti di utilizzo dei componenti;
- illustrare API non direttamente esposte dai componenti
e via dicendo.
Non solo documentazione
L’importanza della creazione di “storie” più andare ben oltre alla creazione di una vetrina per i componenti. Infatti, una “storia” è un modo per isolare un comportamento specifico di un determinato componente di cui vogliamo dare evidenza, e in quanto tale abbiamo la necessità che il risultato visivo e interattivo sia quanto più “blindato” in relazione agli sviluppi futuri del componente stesso. In sostanza, si vuole che il componente non muti visivamente con il prosieguo degli sviluppi.
I test di regressione visuale
Il modo di garantire che un certo comportamento sia sempre rispettato è quello di stabilire un test che possa essere verificato in qualunque momento. Possibilmente, un test che si possa eseguire in modo automatico.
Generalmente, il mondo dei test automatici è prerogativa dei test unitari, di integrazione e, in minor parte (a causa della lentezza intrinseca della loro esecuzione), del test end-to-end. Ma oltre a questi, c’è una categoria di test che ha il compito di verificare che l’aspetto di un componente/widget/pagina non abbia variazioni di rilievo rispetto ad una baseline – cioè un riferimento visuale stabilito manualmente. Si tratta dei test di regressione visuale (visual regression test).
Questi test vengono eseguiti effettuando degli screenshot del soggetto tramite sistemi di controllo automatizzato dei browser (come Puppeteer o Playwright), e confrontandoli con la baseline con strumenti come pixelmatch che sono in grado di produrre un’immagine delle differenze visuali e assegnare un valore di scostamento percentuale dal riferimento: se tale valore è oltre una certa soglia predefinita, il test verrà considerato fallito.
Storie e test
A questo punto, la questione è: quali sono i test di regressione visuale che dovremmo creare per i nostri componenti? Si tratta degli aspetti che assumono i nostri componenti a seconda del variare dei parametri che li definiscono. In sostanza, si può assumere che ad ogni storia deve corrispondere un test di regressione visuale.
import { visualDiff } from '@web/test-runner-visual-regression'; import { AlertElement } from 'src/components/alert/alert'; import * as stories from 'test/stories/alert.stories'; describe('Alert visual regression tests', () => { for (const [name, story] of Object.entries(stories)) { it(`Story: ${name}`, async () => { const loaderResults = await Promise.all( (story.loaders ?? []).map(loader => loader()) ); const loaded = loaderResults.reduce( (map, partial) => ({ ...map, ...partial }), {} ); const alertResult = await story( { ...defaultArgs, ...story.args }, { loaded } ); const alert = await fixture(alertResult); await story.play?.(); await visualDiff(alert, `alert_story_${name}`); }); } });
In questo modo, oltre a fornire documentazione, le nostre storie di Storybook contribuiranno a rendere più solida la nostra libreria di componenti tramite test aggiuntivi che vengono definiti con sforzo minimo. Tutto ciò andrà a stringere il connubio tra test e documentazione, nato col fatto che un test ben scritto e definito equivale a documentazione del nostro codice.
In conclusione
Storybook non è l’unico strumenti che possa fare da showcase per i nostri componenti, ma sicuramente è il più completo in relazione alla quantità di framework supportati, alla vastità della community e alla disponibilità di plugin ed estensioni.
Grazie a questi ultimi, Storybook offre anche molteplici integrazioni con gli strumenti tipici di design, quali Figma, Sketch, Zeplin e via dicendo.
Gli approcci sopra descritti possono essere applicati all’uso anche di altre librerie, compreso lo sfruttamento per i test di regressione visuale. Ma qualunque sia la vostra scelta, vi suggeriamo con enfasi l’adozione di un sistema di showcasing dei componenti al fine di agevolare sviluppi e adozioni future.
In Antreem usiamo Storybook già da tempo, ed è sempre stato un aiuto importante per sviluppatori di terze parti, come documentazione per la manutenzione del progetto, e come vetrina per mostrare lo stato dell’arte ai committenti. In ultimo è stato sfruttato con efficacia anche per i test di regressione visuale, che arricchiscono l’arsenale a disposizione per la creazione di software stabile e mantenibile nel tempo.