Vincent Barrault

Générer des fichiers avec un projet Schematics

Générer des fichiers avec un projet Schematics

Table des matières

Installer Schematics

Pour générer un projet Schematics, il existe un utilitaire qui s'appelle schematics-cli que je vais installer avec la commande suivante:

npm install -g @angular-devkit/schematics-cli

Créer un nouveau projet Schematics

En me plaçant dans un répertoire de travail et en exécutant cette suite d'instructions, je vais générer mon projet avec un premier schéma à l'interieur.

schematics blank --name=test-generator
cd test-generator
yarn install

Dans mon exemple, je voudrais créer un projet qui mettra à disposition des commandes de génération de tests unitaires. Je vais donc renommer le schéma initial comme ceci:

mv src/test-generator src/test-suite

Et je modifie le fichier de collection comme ceci:

./src/collection.json
{
    "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json",
    "schematics": {
        "test-suite": {
            "description": "Generate a test suite.",
            "factory": "./test-suite/index#testSuite",
            "schema": "./test-suite/schema.json"
        }
    }
}

Pour me permettre d'utiliser des arguments lors des appels des commandes, je dois les définir au préalable dans un fichier schema.json.

Ce dernier est déjà référencé dans le fichier collection.json.

./src/test-suite/schema.json
{
    "$schema": "http://json-schema.org/draft-07/schema",
    "$id": "TestSuiteSchematics",
    "title": "Test suite Schematics",
    "type": "object",
    "description": "Properties of the test suite schematics",
    "additionalProperties": false,
    "properties": {
        "name": {
            "description": "The name of the test suite",
            "type": "string",
            "$default": {
                "$source": "argv",
                "index": 0
            },
            "x-prompt": "What is the name of your test suite ?"
        }
    },
    "required": [
        "name"
    ]
}

Avec cette configuration, je peux definir le type, la valeur par défaut et même le texte affiché à la console quand le schéma demande de remplir la variable.

Ecrire le comportement de notre schéma

Le fichier de configuration collection.json liste les schémas disponibles dans le projet, chaque schéma mène vers une règle qui manipule les fichiers.

./src/test-suite/index.ts
import { strings } from '@angular-devkit/core';
import { apply, mergeWith, Rule, SchematicContext, Tree, url, template } from '@angular-devkit/schematics';

export function testSuite(_options: any): Rule {
    return (tree: Tree, _context: SchematicContext) => {
        const sourceTemplates = url('./files');
        const sourceParametrizedTemplates = apply(sourceTemplates, [
            template({
                ..._options,
                ...strings,
            }),
        ]);

        return mergeWith(sourceParametrizedTemplates)(tree, _context);
    };
}

Ici, la règle est de prendre les fichiers dans le dossier files et de s'en servir comme modèmle pour générer notre suite de tests.

./src/test-suite/files/__name@dasherize__.spec.ts
describe('<%=name%>', () => {
    it('the first test of this test suite.', () => {
        expect(true).toBe(true);
    });
});

Et voici le contenu du modèle. Les emplacements <%=name%> sont remplacés lors de la génération par le contenu de la variable name.

Pour le nom du fichier, tout ce qui est entouré de __ sera aussi remplacé par des variables. Le @dasherize permet d'appliquer une modification sur la variable, ici de transformer la variable de camlCase en kebab-case

Tester son schéma

Pour lancer le schéma depuis le projet Schematics, je dois en premier lieu builder le projet et lancer la commande schematics .:[name-of-schema].

yarn build
schematics .:test-suite --debug=false
prompt: MyFirst

Le --debug=false permet de générer le fichier car, par défaut, le mode debug est activé et previent de la génération des fichiers dans le projet.

Voici le resultat obtenu:

./my-first.spec.ts
describe('MyFirst', () => {
    it('the first test of this test suite.', () => {
        expect(true).toBe(true);
    });
});

Utilisation dans une application

La véritable utilité d'un projet Schehmatics est de l'utiliser dans une application. Je vais pour l'exemple créer une petite application Angular et ajouter la dépendance à mon projet Schematics.

ng new my-angular-application
cd my-angular-application
npm link /path/of/test-generator

Après installation, la commande de génération est disponible avec l'utilitaire ng generate.

ng generate test-generator:test-suite
prompt: MyFirstFromApp

Voici le resultat obtenu:

./my-first-from-app.spec.ts
describe('MyFirstFromApp', () => {
    it('the first test of this test suite.', () => {
        expect(true).toBe(true);
    });
});