import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
import { Tree } from '@angular-devkit/schematics';

import * as prettier from 'prettier';
import * as path from 'path';

import { createEmptyWorkspace } from '../testing-utils';
import { formatFiles } from './format-files';
import { serializeJson } from '../fileutils';
import * as appRoot from 'app-root-path';

describe('formatFiles', () => {
  let tree: Tree;
  let schematicRunner: SchematicTestRunner;
  beforeEach(() => {
    schematicRunner = new SchematicTestRunner(
      '@nrwl/schematics',
      path.join(__dirname, '../../collection.json')
    );
    spyOn(prettier, 'format').and.callFake(input => 'formated :: ' + input);
    tree = Tree.empty();
  });

  it('should format created files', async () => {
    spyOn(prettier, 'resolveConfig').and.returnValue(
      Promise.resolve({
        printWidth: 80
      })
    );
    tree.create('a.ts', 'const a=a');
    const result = await schematicRunner
      .callRule(formatFiles(), tree)
      .toPromise();
    expect(prettier.format).toHaveBeenCalledWith('const a=a', {
      printWidth: 80,
      filepath: appRoot.resolve('a.ts')
    });
    expect(result.read('a.ts').toString()).toEqual('formated :: const a=a');
  });

  it('should not format deleted files', async () => {
    spyOn(prettier, 'resolveConfig').and.returnValue(
      Promise.resolve({
        printWidth: 80
      })
    );
    tree.create('b.ts', '');
    tree.delete('b.ts');
    await schematicRunner.callRule(formatFiles(), tree).toPromise();
    expect(prettier.format).not.toHaveBeenCalledWith(
      'const b=b',
      jasmine.anything()
    );
  });

  it('should format overwritten files', async () => {
    spyOn(prettier, 'resolveConfig').and.returnValue(Promise.resolve(null));
    tree.create('a.ts', 'const a=a');
    tree.overwrite('a.ts', 'const a=b');
    const result = await schematicRunner
      .callRule(formatFiles(), tree)
      .toPromise();
    expect(prettier.format).toHaveBeenCalledWith('const a=b', {
      filepath: appRoot.resolve('a.ts')
    });
    expect(result.read('a.ts').toString()).toEqual('formated :: const a=b');
  });

  it('should not format renamed files', async () => {
    spyOn(prettier, 'resolveConfig').and.returnValue(Promise.resolve(null));
    tree.create('a.ts', 'const a=a');
    tree.rename('a.ts', 'b.ts');
    const result = await schematicRunner
      .callRule(formatFiles(), tree)
      .toPromise();
    expect(prettier.format).toHaveBeenCalledWith('const a=a', {
      filepath: appRoot.resolve('b.ts')
    });
    expect(result.read('b.ts').toString()).toEqual('formated :: const a=a');
  });

  describe('--skip-format', () => {
    it('should not format created files', async () => {
      spyOn(prettier, 'resolveConfig').and.returnValue(
        Promise.resolve({
          printWidth: 80
        })
      );
      tree.create('a.ts', 'const a=a');
      const result = await schematicRunner
        .callRule(
          formatFiles({
            skipFormat: true
          }),
          tree
        )
        .toPromise();
      expect(prettier.format).not.toHaveBeenCalledWith('const a=a', {
        printWidth: 80,
        filepath: appRoot.resolve('a.ts')
      });
      expect(result.read('a.ts').toString()).toEqual('const a=a');
    });
  });
});
