karma template | | Cell 1 | Search

This code automates the creation of Angular component test files by finding component .ts files, generating corresponding .spec.ts files using a template, and filling in component titles and import statements.

Run example

npm run import -- "Generate a bunch of spec files"

Generate a bunch of spec files

var execSync = require('child_process').execSync;
try {
    require.resolve('glob');
} catch (e) {
    execSync('npm install glob');
}
var fs = require('fs');
var glob = require('glob');
var path = require('path');

var cwd = 'C:\\Users\\brian.cullinan\\Documents\\portal\\src';

var spec = `
import {ComponentFixture} from '@angular/core/testing';
import {} from 'jasmine';
import {MockBackend} from '@angular/http/testing';
import {Router} from '@angular/router';
import {Location} from '@angular/common';
import {By} from '@angular/platform-browser';
import {Core} from '../../../testing/core';
{import}

describe('{title}', function () {
    let fixture: ComponentFixture<{title}>;
    let router: Router;
    let location: Location;
    let xhr: MockBackend;
    let comp: {title};

    beforeEach(() => {
        fixture = Core.createAppWithShared([], [], [{title}]);
        comp = fixture.componentInstance;
        router = fixture.debugElement.injector.get(Router);
        xhr = fixture.debugElement.injector.get(MockBackend);
        location = fixture.debugElement.injector.get(Location);
    });

    it('should load {title}', (done) => {
        fixture.whenStable().then(() => {
            expect(comp).not.toBeNull();
            done();
        });
    });

});
`;

var files = glob.sync('**/*component.ts', {
    ignore: '**/*.spec.ts',
    cwd: cwd
});

var titles = files.map(f => {
    var name = f.split('.')[0].split('/').pop();
    var ucFirst = name.replace(/(^|\s|-)([a-z])/g, (m, p1, p2) => p1 + p2.toUpperCase());
    return ucFirst.replace(/-/ig, '') + 'Component';
});

titles.forEach((t, i) => {
    try {
        var specPath = path.join(cwd, files[i].replace('.ts', '.spec.ts'));
        if (fs.existsSync(specPath)) {
            return;
        }
        var fileStr = files[i].split('/').pop().replace('.ts', '');
        var importStr = 'import {' + t + '} from \'./' + fileStr + '\';';
        fs.writeFileSync(specPath, spec
            .replace(/\{title\}/ig, t)
            .replace(/\{import\}/ig, importStr));
    } catch (e) {
    }
});


What the code could have been:

const fs = require('fs');
const glob = require('glob-promise');
const path = require('path');

const cwd = 'C:\\Users\\brian.cullinan\\Documents\\portal\\src';

// Import required modules, install glob if not exist
try {
    require.resolve('glob-promise');
} catch (e) {
    require('npm').install(['glob-promise'], (err) => {
        if (err) {
            console.error(err);
            process.exit(1);
        }
    });
}

const template = `
import {ComponentFixture} from '@angular/core/testing';
import {} from 'jasmine';
import {MockBackend} from '@angular/http/testing';
import {Router} from '@angular/router';
import {Location} from '@angular/common';
import {By} from '@angular/platform-browser';
import {Core} from '../../../testing/core';
{import}

describe('{title}', function () {
    let fixture: ComponentFixture<{title}>;
    let router: Router;
    let location: Location;
    let xhr: MockBackend;
    let comp: {title};

    beforeEach(() => {
        fixture = Core.createAppWithShared([], [], [{title}]);
        comp = fixture.componentInstance;
        router = fixture.debugElement.injector.get(Router);
        xhr = fixture.debugElement.injector.get(MockBackend);
        location = fixture.debugElement.injector.get(Location);
    });

    it('should load {title}', (done) => {
        fixture.whenStable().then(() => {
            expect(comp).not.toBeNull();
            done();
        });
    });

});
`;

// Function to convert string to camel case
function toCamelCase(str) {
    return str.replace(/(^|\s|-)([a-z])/g, (m, p1, p2) => p1 + p2.toUpperCase()).replace(/-/ig, '');
}

// Function to generate spec file
async function generateSpec(file) {
    try {
        const title = toCamelCase(file.split('.')[0].split('/').pop());
        const specFile = path.join(cwd, file.replace('.ts', '.spec.ts'));
        if (fs.existsSync(specFile)) {
            return;
        }
        const importStr = `import ${title} from './${file.split('.')[0]}'`;
        await fs.promises.writeFile(specFile, template
           .replace(/\{title\}/ig, title)
           .replace(/\{import\}/ig, importStr)
        );
    } catch (e) {
        console.error(e);
    }
}

// Get list of component files
const files = await glob('**/*component.ts', {
    ignore: '**/*.spec.ts',
    cwd: cwd
});

// Generate spec files
await Promise.all(files.map(generateSpec));

This code generates Angular component test files using a template.

Here's a breakdown:

  1. Dependencies:

  2. Install Glob:

  3. Configuration:

  4. Template:

  5. File Search:

  6. Component Titles:

  7. Test File Generation:

In essence, this script automates the creation of Angular component test files based on a template and the existing component files in a directory.