/**
 * @license
 * Copyright Google LLC 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.dev/license
 */

import { Architect } from '@angular-devkit/architect';
import { JsonObject, normalize } from '@angular-devkit/core';
import { createArchitect, host, protractorTargetSpec } from '../../testing/test-utils';

describe('Protractor Builder', () => {
  let architect: Architect;

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

  afterEach(() => host.restore().toPromise());

  it('executes tests with automatic dev server usage', async () => {
    const run = await architect.scheduleTarget(protractorTargetSpec);

    await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: true }));

    await run.stop();
  });

  it('fails with no devServerTarget and no standalone server', async () => {
    const overrides = { devServerTarget: undefined } as unknown as JsonObject;
    const run = await architect.scheduleTarget(protractorTargetSpec, overrides);

    await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: false }));

    await run.stop();
  });

  it('overrides protractor specs', async () => {
    host
      .scopedSync()
      .rename(normalize('./e2e/app.e2e-spec.ts'), normalize('./e2e/renamed-app.e2e.spec.ts'));

    const overrides = { specs: ['./e2e/renamed-app.e2e.spec.ts'] };
    const run = await architect.scheduleTarget(protractorTargetSpec, overrides);

    await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: true }));

    await run.stop();
  });

  it('overrides protractor suites', async () => {
    host
      .scopedSync()
      .rename(normalize('./e2e/app.e2e-spec.ts'), normalize('./e2e/renamed-app.e2e-spec.ts'));

    // Suites block needs to be added in the protractor.conf.js file to test suites
    host.replaceInFile(
      'protractor.conf.js',
      `allScriptsTimeout: 11000,`,
      `
      allScriptsTimeout: 11000,
      suites: {
        app: './e2e/app.e2e-spec.ts'
      },
    `,
    );

    const overrides = { suite: 'app' };
    const run = await architect.scheduleTarget(protractorTargetSpec, overrides);

    await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: true }));

    await run.stop();
  });

  it('supports automatic port assignment (port = 0)', async () => {
    const overrides = { port: 0 };
    const run = await architect.scheduleTarget(protractorTargetSpec, overrides);

    await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: true }));

    await run.stop();
  });

  it('supports dev server builder with browser builder base HREF option', async () => {
    host.replaceInFile(
      'angular.json',
      '"main": "src/main.ts",',
      '"main": "src/main.ts", "baseHref": "/base/",',
    );
    // Need to reset architect to use the modified config
    architect = (await createArchitect(host.root())).architect;

    const run = await architect.scheduleTarget(protractorTargetSpec);

    await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: true }));

    await run.stop();
  });

  it('supports running tests by pattern', async () => {
    host.writeMultipleFiles({
      'e2e/app.e2e-spec.ts': `
        it('should succeed', () => expect(true).toBeTruthy());
        it('should fail', () => expect(false).toBeTruthy());
      `,
    });

    const overrides = { grep: 'succeed' };

    const run = await architect.scheduleTarget(protractorTargetSpec, overrides);

    await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: true }));

    await run.stop();
  });

  it('supports running tests excluding a pattern', async () => {
    host.writeMultipleFiles({
      'e2e/app.e2e-spec.ts': `
        it('should succeed', () => expect(true).toBeTruthy());
        it('should fail', () => expect(false).toBeTruthy());
      `,
    });

    const overrides = { grep: 'fail', invertGrep: true };

    const run = await architect.scheduleTarget(protractorTargetSpec, overrides);

    await expectAsync(run.result).toBeResolvedTo(jasmine.objectContaining({ success: true }));

    await run.stop();
  });
});
