<commit_before>/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */
// tslint:disable:no-big-function
import { Architect } from '@angular-devkit/architect';
import { TestLogger } from '@angular-devkit/architect/testing';
import { join, logging, normalize, virtualFs } from '@angular-devkit/core';
import { debounceTime, take, takeWhile, tap } from 'rxjs/operators';
import {
  createArchitect,
  host,
  ivyEnabled,
  lazyModuleFiles,
  lazyModuleFnImport,
  outputPath,
} from '../utils';

describe('Browser Builder rebuilds', () => {
  const target = { project: 'app', target: 'build' };
  let architect: Architect;

  beforeEach(async () => {
    await host.initialize().toPromise();
    architect = (await createArchitect(host.root())).architect;
  });
  afterEach(async () => host.restore().toPromise());

  it('rebuilds on TS file changes', async () => {
    const goldenValueFiles: { [path: string]: string } = {
      'src/app/app.module.ts': `
        import { BrowserModule } from '@angular/platform-browser';
        import { NgModule } from '@angular/core';

        import { AppComponent } from './app.component';

        @NgModule({
          declarations: [
            AppComponent
          ],
          imports: [
            BrowserModule
          ],
          providers: [],
          bootstrap: [AppComponent]
        })
        export class AppModule { }

        console.log('$$_E2E_GOLDEN_VALUE_1');
        export let X = '$$_E2E_GOLDEN_VALUE_2';
      `,
      'src/main.ts': `
        import { enableProdMode } from '@angular/core';
        import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

        import { AppModule } from './app/app.module';
        import { environment } from './environments/environment';

        if (environment.production) {
          enableProdMode();
        }

        platformBrowserDynamic().bootstrapModule(AppModule);

        import * as m from './app/app.module';
        console.log(m.X);
        console.log('$$_E2E_GOLDEN_VALUE_3');
      `,
    };

    const overrides = { watch: true };

    let phase = 1;
    const run = await architect.scheduleTarget(target, overrides);
    await run.output
      .pipe(
        tap(result => {
          expect(result.success).toBe(true, 'build should succeed');
          const hasLazyChunk = host.scopedSync().exists(normalize('dist/lazy-lazy-module.js'));
          switch (phase) {
            case 1:
              // No lazy chunk should exist.
              if (!hasLazyChunk) {
                phase = 2;
                host.writeMultipleFiles({ ...lazyModuleFiles, ...lazyModuleFnImport });
              }
              break;

            case 2:
              // A lazy chunk should have been with the filename.
              if (hasLazyChunk) {
                phase = 3;
                host.writeMultipleFiles(goldenValueFiles);
              }
              break;

            case 3:
              // The golden values should be present and in the right order.
              const re = new RegExp(
                /\$\$_E2E_GOLDEN_VALUE_1(.|\n|\r)*/.source +
                  /\$\$_E2E_GOLDEN_VALUE_2(.|\n|\r)*/.source +
                  /\$\$_E2E_GOLDEN_VALUE_3/.source,
              );
              const fileName = './dist/main.js';
              const content = virtualFs.fileBufferToString(
                host.scopedSync().read(normalize(fileName)),
              );

              if (re.test(content)) {
                phase = 4;
              }
              break;
          }
        }),
        takeWhile(() => phase < 4),
      )
      .toPromise();
    await run.stop();
  });

  it('rebuilds on CSS changes', async () => {
    const overrides = { watch: true };

    const run = await architect.scheduleTarget(target, overrides);
    await run.output
      .pipe(
        debounceTime(500),
        tap(buildEvent => expect(buildEvent.success).toBe(true)),
        tap(() => host.appendToFile('src/app/app.component.css', ':host { color: blue; }')),
        take(2),
      )
      .toPromise();
    await run.stop();
  });

  it('type checks on rebuilds', async () => {
    host.writeMultipleFiles({
      'src/funky2.ts': `export const funky2 = (value: string) => value + 'hello';`,
      'src/funky.ts': `export * from './funky2';`,
    });
    host.appendToFile(
      'src/main.ts',
      `
      import { funky2 } from './funky';
      console.log(funky2('town'));
    `,<commit_msg>test: increase/add debounceTime to reduce flakiness<commit_after>/**
 * @license
 * Copyright Google Inc. All Rights Reserved.
 *
 * Use of this source code is governed by an MIT-style license that can be
 * found in the LICENSE file at https://angular.io/license
 */
// tslint:disable:no-big-function
import { Architect } from '@angular-devkit/architect';
import { TestLogger } from '@angular-devkit/architect/testing';
import { join, logging, normalize, virtualFs } from '@angular-devkit/core';
import { debounceTime, take, takeWhile, tap } from 'rxjs/operators';
import {
  createArchitect,
  host,
  ivyEnabled,
  lazyModuleFiles,
  lazyModuleFnImport,
  outputPath,
} from '../utils';

describe('Browser Builder rebuilds', () => {
  const target = { project: 'app', target: 'build' };
  let architect: Architect;

  beforeEach(async () => {
    await host.initialize().toPromise();
    architect = (await createArchitect(host.root())).architect;
  });
  afterEach(async () => host.restore().toPromise());

  it('rebuilds on TS file changes', async () => {
    const goldenValueFiles: { [path: string]: string } = {
      'src/app/app.module.ts': `
        import { BrowserModule } from '@angular/platform-browser';
        import { NgModule } from '@angular/core';

        import { AppComponent } from './app.component';

        @NgModule({
          declarations: [
            AppComponent
          ],
          imports: [
            BrowserModule
          ],
          providers: [],
          bootstrap: [AppComponent]
        })
        export class AppModule { }

        console.log('$$_E2E_GOLDEN_VALUE_1');
        export let X = '$$_E2E_GOLDEN_VALUE_2';
      `,
      'src/main.ts': `
        import { enableProdMode } from '@angular/core';
        import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

        import { AppModule } from './app/app.module';
        import { environment } from './environments/environment';

        if (environment.production) {
          enableProdMode();
        }

        platformBrowserDynamic().bootstrapModule(AppModule);

        import * as m from './app/app.module';
        console.log(m.X);
        console.log('$$_E2E_GOLDEN_VALUE_3');
      `,
    };

    const overrides = { watch: true };

    let phase = 1;
    const run = await architect.scheduleTarget(target, overrides);
    await run.output
      .pipe(
        debounceTime(1000),
        tap(result => {
          expect(result.success).toBe(true, 'build should succeed');
          const hasLazyChunk = host.scopedSync().exists(normalize('dist/lazy-lazy-module.js'));
          switch (phase) {
            case 1:
              // No lazy chunk should exist.
              if (!hasLazyChunk) {
                phase = 2;
                host.writeMultipleFiles({ ...lazyModuleFiles, ...lazyModuleFnImport });
              }
              break;

            case 2:
              // A lazy chunk should have been with the filename.
              if (hasLazyChunk) {
                phase = 3;
                host.writeMultipleFiles(goldenValueFiles);
              }
              break;

            case 3:
              // The golden values should be present and in the right order.
              const re = new RegExp(
                /\$\$_E2E_GOLDEN_VALUE_1(.|\n|\r)*/.source +
                  /\$\$_E2E_GOLDEN_VALUE_2(.|\n|\r)*/.source +
                  /\$\$_E2E_GOLDEN_VALUE_3/.source,
              );
              const fileName = './dist/main.js';
              const content = virtualFs.fileBufferToString(
                host.scopedSync().read(normalize(fileName)),
              );

              if (re.test(content)) {
                phase = 4;
              }
              break;
          }
        }),
        takeWhile(() => phase < 4),
      )
      .toPromise();
    await run.stop();
  });

  it('rebuilds on CSS changes', async () => {
    const overrides = { watch: true };

    const run = await architect.scheduleTarget(target, overrides);
    await run.output
      .pipe(
        debounceTime(1000),
        tap(buildEvent => expect(buildEvent.success).toBe(true)),
        tap(() => host.appendToFile('src/app/app.component.css', ':host { color: blue; }')),
        take(2),
      )
      .toPromise();
    await run.stop();
  });

  it('type checks on rebuilds', async () => {
    host.writeMultipleFiles({
      'src/funky2.ts': `export const funky2 = (value: string) => value + 'hello';`,
      'src/funky.ts': `export * from './funky2';`,
    });
    host.appendToFile(
      'src/main.ts',
      `
      import { funky2 } from './funky';
      console.log(funky2('town'));
    `,
{'fraction_non_alphanumeric': 0.13962751641726773, 'fraction_numerical': 0.006782215523737754, 'mean_word_length': 1.9852185089974292, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 25, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6080424', 'n_tokens_mistral': 2743, 'n_tokens_neox': 2652, 'n_words': 602}