import { checkFilesDoNotExist, checkFilesExist, killPorts, newProject, readFile, readJson, rmDist, runCLI, uniq, updateFile, } from '@nrwl/e2e/utils'; import { names } from '@nrwl/devkit'; describe('Build React libraries and apps', () => { /** * Graph: * * childLib * / * app => parentLib => * \ * childLib2 * */ let app: string; let parentLib: string; let childLib: string; let childLib2: string; let buildableParentLib: string; let buildableChildLib: string; let buildableChildLib2: string; let proj: string; beforeEach(() => { app = uniq('app'); parentLib = uniq('parentlib'); childLib = uniq('childlib'); childLib2 = uniq('childlib2'); buildableParentLib = uniq('buildableparentlib'); buildableChildLib = uniq('buildablechildlib'); buildableChildLib2 = uniq('buildablechildlib2'); proj = newProject(); // create dependencies by importing const createDep = (parent, children: string[]) => { updateFile( `libs/${parent}/src/index.ts`, ` export * from './lib/${parent}'; ${children .map( (entry) => `import { ${ names(entry).className } } from '@${proj}/${entry}'; console.log(${ names(entry).className });` ) .join('\n')} ` ); }; runCLI(`generate @nrwl/react:app ${app}`); // generate publishable libs runCLI( `generate @nrwl/react:library ${parentLib} --publishable --importPath=@${proj}/${parentLib} --no-interactive` ); runCLI( `generate @nrwl/react:library ${childLib} --publishable --importPath=@${proj}/${childLib} --no-interactive` ); runCLI( `generate @nrwl/react:library ${childLib2} --publishable --importPath=@${proj}/${childLib2} --no-interactive` ); createDep(parentLib, [childLib, childLib2]); updateFile( `apps/${app}/src/main.tsx`, ` import {${names(parentLib).className}} from "@${proj}/${parentLib}"; console.log(${names(parentLib).className}); ` ); // Add assets to child lib updateFile('workspace.json', (c) => { const json = JSON.parse(c); json.projects[childLib].targets.build.options.assets = [ `libs/${childLib}/src/assets`, ]; return JSON.stringify(json, null, 2); }); updateFile(`libs/${childLib}/src/assets/hello.txt`, 'Hello World!'); // generate buildable libs runCLI( `generate @nrwl/react:library ${buildableParentLib} --buildable --no-interactive` ); runCLI( `generate @nrwl/react:library ${buildableChildLib} --buildable --no-interactive` ); runCLI( `generate @nrwl/react:library ${buildableChildLib2} --buildable --no-interactive` ); createDep(buildableParentLib, [buildableChildLib, buildableChildLib2]); // we are setting paths to {} to make sure built libs are read from dist updateFile('tsconfig.base.json', (c) => { const json = JSON.parse(c); json.compilerOptions.paths = {}; return JSON.stringify(json, null, 2); }); }); afterEach(() => killPorts()); describe('Publishable libraries', () => { it('should build libraries with and without dependencies', () => { /* * 1. Without dependencies */ const childLibOutput = runCLI(`build ${childLib}`) // FIX for windows and OSX where output names might get broken to multipleline .replace(/\s\s\s││\s\s\s/gm, ''); const childLib2Output = runCLI(`build ${childLib2}`) // FIX for windows and OSX where output names might get broken to multipleline .replace(/\s\s\s││\s\s\s/gm, ''); expect(childLibOutput).toContain(`${childLib}.umd.js`); expect(childLibOutput).toContain(`${childLib}.esm.js`); expect(childLibOutput).toContain(`Bundle complete: ${childLib}`); expect(childLib2Output).toContain(`${childLib2}.esm.js`); expect(childLib2Output).toContain(`${childLib2}.umd.js`); expect(childLib2Output).toContain(`Bundle complete: ${childLib2}`); checkFilesExist(`dist/libs/${childLib}/assets/hello.txt`); checkFilesExist(`dist/libs/${childLib2}/README.md`); /* * 2. With dependencies */ let parentLibOutput = runCLI(`build ${parentLib}`) // FIX for windows and OSX where output names might get broken to multipleline .replace(/\s\s\s││\s\s\s/gm, ''); expect(parentLibOutput).toContain(`${parentLib}.esm.js`); expect(parentLibOutput).toContain(`${parentLib}.umd.js`); expect(parentLibOutput).toContain(`Bundle complete: ${parentLib}`); const jsonFile = readJson(`dist/libs/${parentLib}/package.json`); expect(jsonFile.peerDependencies).toEqual( expect.objectContaining({ [`@${proj}/${childLib}`]: '0.0.1', [`@${proj}/${childLib2}`]: '0.0.1', }) ); /* * 3. With dependencies without existing dist */ rmDist(); parentLibOutput = runCLI( `build ${parentLib} --with-deps --skip-nx-cache` ).replace(/\s\s\s││\s\s\s/gm, ''); expect(parentLibOutput).toContain(`Bundle complete: ${parentLib}`); expect(parentLibOutput).toContain(`Bundle complete: ${childLib}`); expect(parentLibOutput).toContain(`Bundle complete: ${childLib2}`); }); it('should preserve the tsconfig target set by user', () => { // Setup const myLib = uniq('my-lib'); runCLI( `generate @nrwl/react:library ${myLib} --publishable=true --importPath="@mproj/${myLib}" --no-interactive` ); /** * * Here I update my library file * I am just adding this in the end: * * export const TestFunction = async () => { * return await Promise.resolve('Done!') * } * * So that I can see the change in the Promise. * */ updateFile(`libs/${myLib}/src/lib/${myLib}.tsx`, (content) => { return ` ${content} \n export const TestFunction = async () => { return await Promise.resolve('Done!') } `; }); updateFile(`libs/${myLib}/tsconfig.json`, (content) => { const json = JSON.parse(content); /** * Set target as es3!! */ json.compilerOptions.target = 'es3'; return JSON.stringify(json, null, 2); }); // What we're testing runCLI(`build ${myLib}`); // Assertion const content = readFile(`dist/libs/${myLib}/${myLib}.esm.js`); /** * Then check if the result contains this "promise" polyfill? */ expect(content).toContain('function __generator(thisArg, body) {'); }); it('should build an app composed out of publishable libs', () => { const buildWithDeps = runCLI( `build ${app} --with-deps --buildLibsFromSource=false` ); expect(buildWithDeps).toContain(`Running target "build" succeeded`); checkFilesDoNotExist(`apps/${app}/tsconfig/tsconfig.nx-tmp`); // we remove all path mappings from the root tsconfig, so when trying to build // libs from source, the builder will throw const failedBuild = runCLI( `build ${app} --with-deps --buildLibsFromSource`, { silenceError: true } ); expect(failedBuild).toContain(`Can't resolve`); }, 1000000); }); });