fs-extra#ensureDirSync TypeScript Examples

The following examples show how to use fs-extra#ensureDirSync. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From dendron with GNU Affero General Public License v3.0 7 votes vote down vote up
/**
   * downloads the image from cdn url and stores them in the assets directory inside vault
   */
  static downloadImage = (
    imageUrl: string | undefined,
    assetDir: string,
    text: string
  ): string => {
    fs.ensureDirSync(assetDir);
    if (imageUrl) {
      const uuid = genUUIDInsecure();
      const dest = path.join(assetDir, `image-${uuid}.png`);
      const options = {
        url: imageUrl,
        dest,
      };
      try {
        text += `![image](assets/image-${uuid}.png)\n`;
        download.image(options);
      } catch (err: any) {
        throw new DendronError({
          message: stringifyError(err),
          severity: ERROR_SEVERITY.MINOR,
        });
      }
    }
    return text;
  };
Example #2
Source File: executor.ts    From nx-dotnet with MIT License 6 votes vote down vote up
export default async function runExecutor(
  schema: Partial<UpdateSwaggerJsonExecutorSchema>,
  context: ExecutorContext,
  dotnetClient: DotNetClient = new DotNetClient(dotnetFactory(), workspaceRoot),
) {
  const nxProjectConfiguration = getExecutedProjectConfiguration(context);
  const csProjFilePath = await getProjectFileForNxProject(
    nxProjectConfiguration,
  );

  const options = normalizeOptions(
    schema,
    nxProjectConfiguration,
    csProjFilePath,
    context.projectName as string,
  );
  ensureDirSync(dirname(options.output));

  ensureSwaggerToolInstalled(
    context,
    dotnetClient,
    await readSwashbuckleVersion(csProjFilePath),
  );
  dotnetClient.runTool('swagger', [
    'tofile',
    '--output',
    options.output,
    options.startupAssembly,
    options.swaggerDoc,
  ]);

  return {
    success: true,
  };
}
Example #3
Source File: sqlite3.ts    From backstage with Apache License 2.0 6 votes vote down vote up
/**
 * Creates a knex SQLite3 database connection
 *
 * @param dbConfig - The database config
 * @param overrides - Additional options to merge with the config
 */
export function createSqliteDatabaseClient(
  dbConfig: Config,
  overrides?: Knex.Config,
) {
  const knexConfig = buildSqliteDatabaseConfig(dbConfig, overrides);

  // If storage on disk is used, ensure that the directory exists
  if (
    (knexConfig.connection as Knex.Sqlite3ConnectionConfig).filename &&
    (knexConfig.connection as Knex.Sqlite3ConnectionConfig).filename !==
      ':memory:'
  ) {
    const { filename } = knexConfig.connection as Knex.Sqlite3ConnectionConfig;
    const directory = path.dirname(filename);

    ensureDirSync(directory);
  }

  const database = knexFactory(knexConfig);

  database.client.pool.on('createSuccess', (_eventId: any, resource: any) => {
    resource.run('PRAGMA foreign_keys = ON', () => {});
  });

  return database;
}
Example #4
Source File: index.ts    From nx-dotnet with MIT License 6 votes vote down vote up
export function updateFile(
  f: string,
  content: string | ((content: string) => string),
): void {
  ensureDirSync(path.dirname(tmpProjPath(f)));
  if (typeof content === 'string') {
    writeFileSync(tmpProjPath(f), content);
  } else {
    writeFileSync(
      tmpProjPath(f),
      content(readFileSync(tmpProjPath(f)).toString()),
    );
  }
}
Example #5
Source File: utils.ts    From dendron with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
   * Create config file if it doesn't exist
   */
  static genConfigFile({
    podsDir,
    podClass,
    force,
  }: {
    podsDir: string;
    podClass: PodClassEntryV4;
    force?: boolean;
  }) {
    const podConfigPath = PodUtils.getConfigPath({ podsDir, podClass });
    ensureDirSync(path.dirname(podConfigPath));
    // eslint-disable-next-line new-cap
    const pod = new podClass();
    const required = pod.config.required;
    const podConfig = pod.config.properties;
    const config = Object.keys(podConfig)
      .map((ent: any) => {
        podConfig[ent] = _.defaults(podConfig[ent], { default: "TODO" });
        const args = [
          `# description: ${podConfig[ent].description}`,
          `# type: ${podConfig[ent].type}`,
        ];
        let configPrefix = "# ";
        if (required.includes(`${ent}`)) {
          args.push(`# required: true`);
          configPrefix = "";
        }
        args.push(`${configPrefix}${ent}: ${podConfig[ent].default}`);
        return args.join("\n");
      })
      .join("\n\n");

    if (!fs.existsSync(podConfigPath) || force) {
      writeFileSync(podConfigPath, config);
    }
    return podConfigPath;
  }
Example #6
Source File: express.adapter.ts    From nx-plugins with MIT License 5 votes vote down vote up
deploy(
    context: BuilderContext,
    cwd: string,
    options: NxDeployItDeployBuilderSchema,
    configuration: string,
    targetOptions: any
  ): Observable<BuilderOutput> {
    const distributationPath = getDistributionPath(context);

    const project = getProjectConfig(context);
    const infrastructureFolder = resolve(
      context.workspaceRoot,
      project.root,
      'infrastructure'
    );

    const processCwd = process.cwd();
    process.chdir(infrastructureFolder);

    const build$: Observable<BuilderOutput> = from(
      ncc(resolve(infrastructureFolder, 'functions/main/index.ts'), {
        cache: resolve(infrastructureFolder, 'buildcache')
      })
    ).pipe(
      map(
        (buildResult: {
          code: string;
          asset: { [index: string]: { source: string } };
        }) => {
          process.chdir(processCwd);
          ensureDirSync(resolve(infrastructureFolder, 'functions/dist/main'));
          // compiled javascript
          writeFileSync(
            resolve(infrastructureFolder, 'functions/dist/main/index.js'),
            buildResult.code
          );
          // assets
          for (const file in buildResult.asset) {
            const content = buildResult.asset[file];
            ensureFileSync(
              resolve(infrastructureFolder, `functions/dist/main/${file}`)
            );
            writeFileSync(
              resolve(infrastructureFolder, `functions/dist/main/${file}`),
              content.source.toString()
            );
          }
          return { success: true };
        }
      )
    );

    return build$.pipe(
      switchMap(() =>
        this.up(
          cwd,
          options,
          configuration,
          targetOptions,
          distributationPath,
          context.target.project
        )
      )
    );
  }
Example #7
Source File: dryrun.ts    From algo-builder with Apache License 2.0 5 votes vote down vote up
// write (dryrun dump) to file in `cache/dryrun`
	protected writeFile(filename: string, content: Uint8Array | string): void {
		ensureDirSync(path.dirname(filename));
		fs.writeFileSync(filename, content);
	}
Example #8
Source File: index.ts    From nx-dotnet with MIT License 5 votes vote down vote up
export function renameFile(f: string, newPath: string): void {
  ensureDirSync(path.dirname(tmpProjPath(newPath)));
  renameSync(tmpProjPath(f), tmpProjPath(newPath));
}
Example #9
Source File: ConfigFileUtils.ts    From dendron with GNU Affero General Public License v3.0 5 votes vote down vote up
/**
   * Create config file if it doesn't exist
   */
  static genConfigFileV2<T>({
    fPath,
    configSchema,
    force,
    setProperties,
  }: {
    fPath: string;
    configSchema: any;
    force?: boolean;
    setProperties?: Partial<T>;
  }) {
    ensureDirSync(path.dirname(fPath));
    const required = configSchema.required;
    const podConfig = configSchema.properties;
    const config = Object.keys(podConfig)
      .map((ent: any) => {
        podConfig[ent] = _.defaults(podConfig[ent], { default: "TODO" });
        const args = [
          `# description: ${podConfig[ent].description}`,
          `# type: ${podConfig[ent].type}`,
        ];
        let configPrefix = "# ";
        if (required.includes(`${ent}`)) {
          args.push(`# required: true`);
          configPrefix = "";
        }

        // If a pre-set value for an optional param has been passed in, then keep it.
        if (setProperties && ent in setProperties) {
          configPrefix = "";
        }

        /**
         * add NOTE for config options having note property. Mark the option as a comment.
         * added for exportScope config option
         */
        if (podConfig[ent].note) {
          args.push(`# NOTE: ${podConfig[ent].note}`);
          configPrefix = "# ";
        }
        args.push(
          `${configPrefix}${ent}: ${
            setProperties && ent in setProperties
              ? setProperties[ent as keyof T]
              : podConfig[ent].default
          }`
        );
        return args.join("\n");
      })
      .join("\n\n");

    const fileExists = fs.existsSync(fPath);
    if (!fileExists || force) {
      writeFileSync(fPath, config);
    } else if (fileExists && !force) {
      throw new Error("Config already exists!");
    }
    return fPath;
  }
Example #10
Source File: ImportPod.test.ts    From dendron with GNU Affero General Public License v3.0 5 votes vote down vote up
suite("ImportPod", function () {
  let ctx: vscode.ExtensionContext;
  ctx = setupBeforeAfter(this, {
    beforeHook: () => {},
  });

  test("json", (done) => {
    runLegacyMultiWorkspaceTest({
      ctx,
      postSetupHook: async ({ wsRoot, vaults }) => {
        await PODS_CORE.JSON.IMPORT.BASIC.preSetupHook({ wsRoot, vaults });
      },
      onInit: async ({ vaults, wsRoot }) => {
        const podClass = JSONImportPod;
        const podsDir = path.join(wsRoot, "pods");
        const configPath = PodUtils.getConfigPath({ podsDir, podClass });

        const fakePod = (): DPod<any> => {
          return {
            config: [],
            execute: async ({ config }) => {
              ensureDirSync(path.dirname(configPath));
              writeYAML(configPath, config);

              const cmd = new ImportPodCommand();
              const podChoice = podClassEntryToPodItemV4(JSONImportPod);
              // @ts-ignore
              cmd.gatherInputs = async () => {
                return { label: "", podChoice };
              };
              await cmd.run();
            },
          };
        };
        const pod = fakePod();
        const engine = getDWorkspace().engine;
        await PODS_CORE.JSON.IMPORT.BASIC.testFunc({
          engine,
          wsRoot,
          vaults,
          extra: { pod },
          initResp: {} as any,
        });
        done();
      },
    });
  });
});
Example #11
Source File: ConfigurePod.spec.ts    From dendron with GNU Affero General Public License v3.0 5 votes vote down vote up
suite("ConfigurePod", function () {
  let root: DirResult;
  let ctx: vscode.ExtensionContext;
  let podsDir: string;

  ctx = setupBeforeAfter(this, {
    beforeHook: () => {
      root = tmpDir();
      podsDir = path.join(root.name, "pods");
    },
  });

  test("no config", (done) => {
    runLegacyMultiWorkspaceTest({
      ctx,
      preSetupHook: ENGINE_HOOKS.setupBasic,
      onInit: async ({}) => {
        const cmd = new ConfigurePodCommand();
        const podChoice = podClassEntryToPodItemV4(JSONExportPod);
        cmd.gatherInputs = async () => {
          return { podClass: podChoice.podClass };
        };
        await cmd.run();
        const activePath =
          VSCodeUtils.getActiveTextEditor()?.document.uri.fsPath;
        expect(
          activePath?.endsWith("pods/dendron.json/config.export.yml")
        ).toBeTruthy();
        done();
      },
    });
  });

  test("config present", (done) => {
    runLegacyMultiWorkspaceTest({
      ctx,
      preSetupHook: ENGINE_HOOKS.setupBasic,
      onInit: async ({}) => {
        const cmd = new ConfigurePodCommand();
        const podChoice = podClassEntryToPodItemV4(JSONExportPod);
        const podClass = podChoice.podClass;
        cmd.gatherInputs = async () => {
          return { podClass };
        };

        // setup
        const configPath = PodUtils.getConfigPath({ podsDir, podClass });
        const exportDest = path.join(
          PodUtils.getPath({ podsDir, podClass }),
          "export.json"
        );
        ensureDirSync(path.dirname(configPath));

        writeYAML(configPath, { dest: exportDest });
        await cmd.run();
        const activePath =
          VSCodeUtils.getActiveTextEditor()?.document.uri.fsPath;
        expect(
          activePath?.endsWith("pods/dendron.json/config.export.yml")
        ).toBeTruthy();
        done();
      },
    });
  });
});
Example #12
Source File: ConfigureExportPodV2.spec.ts    From dendron with GNU Affero General Public License v3.0 5 votes vote down vote up
suite("Configure ExportPod V2 ", function () {
  const ctx = setupBeforeAfter(this, {
    afterHook: () => {
      sinon.restore();
    },
  });
  describe("GIVEN Configure Export V2 is run", () => {
    describeMultiWS(
      "WHEN New Export option is selected from the Quickpick",
      {
        ctx,
        preSetupHook: ENGINE_HOOKS.setupBasic,
      },
      () => {
        test("THEN new config must be created", async () => {
          const cmd = new ConfigureExportPodV2();
          sinon
            .stub(PodUIControls, "promptForExportConfigOrNewExport")
            .returns(Promise.resolve("New Export"));
          const podType = PodV2Types.GoogleDocsExportV2;
          sinon
            .stub(PodUIControls, "promptForPodType")
            .returns(Promise.resolve(podType));
          sinon
            .stub(PodUIControls, "promptForGenericId")
            .returns(Promise.resolve("foo"));
          await cmd.run();
          const activePath =
            VSCodeUtils.getActiveTextEditor()?.document.uri.fsPath;
          expect(
            activePath?.endsWith(path.join("pods", "custom", "config.foo.yml"))
          ).toBeTruthy();
        });
      }
    );

    describeMultiWS(
      "AND WHEN a custom pod ID is selected",
      {
        ctx,
        preSetupHook: ENGINE_HOOKS.setupBasic,
      },
      () => {
        test("THEN config of selected podId must open", async () => {
          const cmd = new ConfigureExportPodV2();
          sinon
            .stub(PodUIControls, "promptForExportConfigOrNewExport")
            .returns(Promise.resolve({ podId: "foobar" }));
          //setup
          const { wsRoot } = ExtensionProvider.getDWorkspace();
          const configPath = PodUtils.getCustomConfigPath({
            wsRoot,
            podId: "foobar",
          });
          ensureDirSync(path.dirname(configPath));
          writeYAML(configPath, {
            podType: PodV2Types.MarkdownExportV2,
            podId: "foobar",
            exportScope: "Note",
          });

          await cmd.run();
          const activePath =
            VSCodeUtils.getActiveTextEditor()?.document.uri.fsPath;
          expect(
            activePath?.endsWith(
              path.join("pods", "custom", "config.foobar.yml")
            )
          ).toBeTruthy();
        });
      }
    );
  });
});
Example #13
Source File: project.spec.ts    From cli with Apache License 2.0 5 votes vote down vote up
mockedCreateFileSync = jest.mocked(ensureDirSync)
Example #14
Source File: dotFolder.ts    From cli with Apache License 2.0 5 votes vote down vote up
private ensureFolderExists() {
    ensureDirSync(this.path);
  }
Example #15
Source File: image-compressor.ts    From image-optimizer with MIT License 5 votes vote down vote up
#optimize (files: DroppedFile[]) {
    files.forEach(async file => {
      if (!Object.values(MIME_TYPE_ENUM).includes(file.type)) {
        return
      }

      if (isFile(file.path)) {
        const { name, ext, dir } = path.parse(file.path)
        const isAddToSubfolder = store.app.get('addToSubfolder')

        const fileName = store.app.get('addMinSuffix')
          ? `${name}${MIN_SUFFIX}${ext}`
          : `${name}${ext}`

        const output = isAddToSubfolder
          ? `${dir}/${MIN_FOLDER}/${fileName}`
          : `${dir}/${fileName}`

        if (isAddToSubfolder) {
          ensureDirSync(`${dir}/${MIN_FOLDER}`)
        }

        this.#queue.push(() => this.#processFile(file, output))
      }

      if (isFolder(file.path)) {
        const folderPath = file.path
        const files = (await readdirAsync(file.path)) as string[]
        const _files: DroppedFile[] = []

        files.filter(junk.not).forEach(file => {
          if (isFolder(`${folderPath}/${file}`)) return

          _files.push({
            name: file,
            path: `${folderPath}/${file}`,
            type: mime.lookup(file) as string
          })
        })

        if (_files.length) {
          this.#optimize(_files)
        }
      }
    })

    this.#queue.start()
  }
Example #16
Source File: nestjs.adapter.ts    From nx-plugins with MIT License 5 votes vote down vote up
deploy(
    context: BuilderContext,
    cwd: string,
    options: NxDeployItDeployBuilderSchema,
    configuration: string,
    targetOptions: any
  ): Observable<BuilderOutput> {
    const distributationPath = getDistributionPath(context);

    const project = getProjectConfig(context);
    const infrastructureFolder = resolve(
      context.workspaceRoot,
      project.root,
      'infrastructure'
    );

    const processCwd = process.cwd();
    process.chdir(infrastructureFolder);

    const build$: Observable<BuilderOutput> = from(
      ncc(resolve(infrastructureFolder, 'functions/main/index.ts'), {
        cache: resolve(infrastructureFolder, 'buildcache')
      })
    ).pipe(
      map(
        (buildResult: {
          code: string;
          asset: { [index: string]: { source: string } };
        }) => {
          process.chdir(processCwd);
          ensureDirSync(resolve(infrastructureFolder, 'functions/dist/main'));
          // compiled javascript
          writeFileSync(
            resolve(infrastructureFolder, 'functions/dist/main/index.js'),
            buildResult.code
          );
          // assets
          for (const file in buildResult.asset) {
            const content = buildResult.asset[file];
            ensureFileSync(
              resolve(infrastructureFolder, `functions/dist/main/${file}`)
            );
            writeFileSync(
              resolve(infrastructureFolder, `functions/dist/main/${file}`),
              content.source.toString()
            );
          }
          return { success: true };
        }
      )
    );

    return build$.pipe(
      switchMap(() =>
        this.up(
          cwd,
          options,
          configuration,
          targetOptions,
          distributationPath,
          context.target.project
        )
      )
    );
  }
Example #17
Source File: ensure-complex-nx-project.ts    From nx-plugins with MIT License 5 votes vote down vote up
export function ensureComplexNxProject(...inputs: PluginInput[]): void {
  ensureDirSync(tmpProjPath());
  cleanup();
  runNxNewCommand('', true);
  patchPackageJsonForPlugins(inputs);
  runPackageManagerInstall();
}
Example #18
Source File: ConfigureServiceConnection.spec.ts    From dendron with GNU Affero General Public License v3.0 4 votes vote down vote up
suite("ConfigureServiceConnection", function () {
  const ctx = setupBeforeAfter(this, {
    afterHook: () => {
      sinon.restore();
    },
  });
  describe("GIVEN Configure Service Connection command is run", () => {
    describeMultiWS(
      "WHEN Create New option is selected",
      {
        ctx,
        preSetupHook: ENGINE_HOOKS.setupBasic,
      },
      () => {
        test("THEN new service config must be created", async () => {
          const cmd = new ConfigureServiceConnection();
          sinon.stub(vscode.window, "showQuickPick").returns(
            Promise.resolve({
              label: "Create New Service Connection",
            }) as Thenable<vscode.QuickPickItem>
          );
          const serviceType = ExternalService.Airtable;
          sinon
            .stub(PodUIControls, "promptForExternalServiceType")
            .returns(Promise.resolve(serviceType));
          sinon
            .stub(PodUIControls, "promptForGenericId")
            .returns(Promise.resolve("airtable"));
          await cmd.run();
          const activePath =
            VSCodeUtils.getActiveTextEditor()?.document.uri.fsPath;
          expect(
            activePath?.endsWith(
              path.join("pods", "service-connections", "svcconfig.airtable.yml")
            )
          ).toBeTruthy();
        });
      }
    );

    describeMultiWS(
      "AND WHEN a service connection Id is selected",
      {
        ctx,
        preSetupHook: ENGINE_HOOKS.setupBasic,
      },
      () => {
        test("THEN service config of selected connection Id must open", async () => {
          const cmd = new ConfigureServiceConnection();
          sinon.stub(vscode.window, "showQuickPick").returns(
            Promise.resolve({
              label: "airtable-2",
            }) as Thenable<vscode.QuickPickItem>
          );
          //setup
          const { wsRoot } = ExtensionProvider.getDWorkspace();
          const configPath = PodUtils.getServiceConfigPath({
            wsRoot,
            connectionId: "airtable-2",
          });
          ensureDirSync(path.dirname(configPath));
          writeYAML(configPath, {
            serviceType: ExternalService.Airtable,
            podId: "airtable-2",
            connectionId: "test",
          });
          await cmd.run();
          const activePath =
            VSCodeUtils.getActiveTextEditor()?.document.uri.fsPath;
          expect(
            activePath?.endsWith(
              path.join(
                "pods",
                "service-connections",
                "svcconfig.airtable-2.yml"
              )
            )
          ).toBeTruthy();
        });
      }
    );
  });
});
Example #19
Source File: orgResources.specs.ts    From cli with Apache License 2.0 4 votes vote down vote up
describe('org:resources', () => {
  let testOrgId = '';
  const {accessToken} = getConfig();
  const snapshotProjectPath = join(getUIProjectPath(), 'snapshot-project');
  const defaultTimeout = 10 * 60e3;
  let processManager: ProcessManager;
  let platformClient: PlatformClient;
  const pathToStub = join(cwd(), '__stub__');

  const createNewTerminal = (
    args: string[],
    procManager: ProcessManager,
    cwd: string,
    debugName: string
  ) => {
    return new Terminal('node', args, {cwd}, procManager, debugName);
  };

  const createFieldWithoutUsingSnapshot = async (client: PlatformClient) => {
    await client.field.create({
      description: '',
      facet: false,
      includeInQuery: true,
      includeInResults: true,
      mergeWithLexicon: false,
      multiValueFacet: false,
      multiValueFacetTokenizers: ';',
      name: 'firstfield',
      ranking: false,
      sort: false,
      stemming: false,
      system: false,
      type: FieldTypes.STRING,
      useCacheForComputedFacet: false,
      useCacheForNestedQuery: false,
      useCacheForNumericQuery: false,
      useCacheForSort: false,
    });
  };

  const previewChange = (
    targetOrg: string,
    procManager: ProcessManager,
    debugName = 'org-config-preview'
  ) => {
    const args: string[] = [
      process.env.CLI_EXEC_PATH!,
      'org:resources:preview',
      `-o=${targetOrg}`,
      '--sync',
      '--wait=0',
      '-p=light',
    ];

    return createNewTerminal(args, procManager, snapshotProjectPath, debugName);
  };

  const pushToOrg = async (
    targetOrg: string,
    procManager: ProcessManager,
    debugName = 'org-config-push'
  ) => {
    const args: string[] = [
      process.env.CLI_EXEC_PATH!,
      'org:resources:push',
      '--skipPreview',
      `-o=${targetOrg}`,
      '--wait=0',
    ];
    const pushTerminal = createNewTerminal(
      args,
      procManager,
      snapshotProjectPath,
      debugName
    );

    await pushTerminal.when('exit').on('process').do().once();
  };

  const addOrgIdToModel = (
    fromModelPath: string,
    destinationModelPath: string,
    orgId: string
  ) => {
    const model = readJsonSync(fromModelPath);
    writeJsonSync(destinationModelPath, {...model, orgId});
  };

  const pullFromOrg = async (
    procManager: ProcessManager,
    destinationPath: string,
    additionalFlags: string[] = [],
    debugName: string
  ) => {
    const args: string[] = [
      process.env.CLI_EXEC_PATH!,
      'org:resources:pull',
      '-o',
      '--wait=0',
      '--no-git',
      ...additionalFlags,
    ];

    const pullTerminal = createNewTerminal(
      args,
      procManager,
      destinationPath,
      debugName
    );

    const pullTerminalExitPromise = pullTerminal
      // TODO: CDX-744: understand why cannot use process.on('exit')
      .when(/Project updated/)
      .on('stderr')
      .do()
      .once();

    await pullTerminal
      .when(isGenericYesNoPrompt)
      .on('stderr')
      .do(answerPrompt(`y${EOL}`))
      .until(pullTerminalExitPromise);
  };

  beforeAll(async () => {
    testOrgId = await getTestOrg();
    copySync('snapshot-project', snapshotProjectPath);
    platformClient = getPlatformClient(testOrgId, accessToken);
    processManager = new ProcessManager();
  }, 5 * 60e3);

  afterAll(async () => {
    await processManager.killAllProcesses();
  });

  describe('org:resources:preview', () => {
    describe('when resources are synchronized', () => {
      let stdout = '';
      const stdoutListener = (chunk: string) => {
        stdout += chunk;
      };

      it(
        'should preview the snapshot',
        async () => {
          const previewTerminal = previewChange(
            testOrgId,
            processManager,
            'org-config-preview-sync'
          );

          const expectedOutput = [
            'Extensions',
            '\\+   1 to create',
            'Fields',
            '\\+   2 to create',
          ].join('\\s*');
          const regex = new RegExp(expectedOutput, 'gm');

          previewTerminal.orchestrator.process.stdout.on(
            'data',
            stdoutListener
          );

          const previewTerminalExitPromise = previewTerminal
            .when('exit')
            .on('process')
            .do((proc) => {
              proc.stdout.off('data', stdoutListener);
            })
            .once();

          await previewTerminalExitPromise;
          expect(stdout).toMatch(regex);
        },
        defaultTimeout
      );
    });

    // TODO CDX-753: Create new unsynchronized state for E2E tests.
    describe.skip('when resources are not synchronized', () => {
      let stdout: string;
      let stderr: string;

      const stdoutListener = (chunk: string) => {
        stdout += chunk;
      };
      const stderrListener = (chunk: string) => {
        stderr += chunk;
      };

      beforeAll(async () => {
        stdout = stderr = '';
        await createFieldWithoutUsingSnapshot(platformClient);
      });

      it(
        'should throw a synchronization warning on a field',
        async () => {
          const previewTerminal = previewChange(
            testOrgId,
            processManager,
            'org-config-preview-unsync'
          );

          const process = previewTerminal.orchestrator.process;
          process.stdout.on('data', stdoutListener);
          process.stderr.on('data', stderrListener);

          const previewTerminalExitPromise = previewTerminal
            .when('exit')
            .on('process')
            .do((proc) => {
              proc.stdout.off('data', stdoutListener);
              proc.stderr.off('data', stderrListener);
            })
            .once();

          await previewTerminalExitPromise;
          expect(stdout).toMatch(/Previewing snapshot changes/);
          expect(stderr).toMatch(/Checking for automatic synchronization/);
        },
        defaultTimeout
      );
    });
  });

  describe('org:resources:push', () => {
    beforeAll(async () => {
      await pushToOrg(testOrgId, processManager);
    }, defaultTimeout);

    it('should have pushed fields', async () => {
      const fields = (await platformClient.field.list()).items;
      expect(fields).toEqual(
        expect.arrayContaining([
          expect.objectContaining({name: 'firstfield'}),
          expect.objectContaining({name: 'whereisbrian'}),
        ])
      );
    });

    it('should have pushed extensions', async () => {
      const extensions = await platformClient.extension.list();
      expect(extensions).toEqual(
        expect.arrayContaining([expect.objectContaining({name: 'palpatine'})])
      );
    });
  });

  describe('org:resources:pull', () => {
    const destinationPath = getProjectPath('new-snapshot-project');
    const getResourceFolderContent = (projectPath: string) =>
      readdirSync(join(projectPath, 'resources'));

    beforeEach(() => {
      rmSync(destinationPath, {recursive: true, force: true});
      ensureDirSync(destinationPath);
    });

    it(
      "should pull the org's content",
      async () => {
        await pullFromOrg(
          processManager,
          destinationPath,
          ['-o', testOrgId],
          'org-resources-pull-all'
        );
        const snapshotFiles = readdirSync(snapshotProjectPath);
        const destinationFiles = readdirSync(destinationPath);

        expect(snapshotFiles).toEqual(destinationFiles);
      },
      defaultTimeout
    );

    it(
      'directory should only contain pulled resources and manifest',
      async () => {
        await pullFromOrg(
          processManager,
          destinationPath,
          ['-o', testOrgId, '-r', 'FIELD'],
          'org-resources-pull-all-fields'
        );
        const originalResources = getResourceFolderContent(snapshotProjectPath);
        const destinationResources = getResourceFolderContent(destinationPath);

        expect(destinationResources.length).toBeGreaterThan(0);
        expect(destinationResources.length).toBeLessThan(
          originalResources.length + 1
        );
      },
      defaultTimeout
    );

    it(
      'snapshot should only contain one single field',
      async () => {
        const fixtureModelPath = join(
          pathToStub,
          'snapshotPullModel',
          'oneFieldOnly.json'
        );
        const tmpModel = fileSync({postfix: '.json'});
        addOrgIdToModel(fixtureModelPath, tmpModel.name, testOrgId);
        await pullFromOrg(
          processManager,
          destinationPath,
          ['-m', tmpModel.name],
          'org-resources-pull-one-field'
        );
        const fields = readJsonSync(
          join(destinationPath, 'resources', 'FIELD.json')
        );

        expect(fields.resources.FIELD.length).toBe(1);
      },
      defaultTimeout
    );
  });

  it('should not have any snapshot in the target org', async () => {
    const snapshotlist = await platformClient.resourceSnapshot.list();
    expect(snapshotlist).toHaveLength(0);
  });
});
Example #20
Source File: nx-dotnet.spec.ts    From nx-dotnet with MIT License 4 votes vote down vote up
describe('nx-dotnet e2e', () => {
  beforeAll(() => {
    ensureNxProject('@nx-dotnet/core', 'dist/packages/core');
    initializeGitRepo(e2eDir);
  }, 1500000);

  it('should create apps, libs, and project references', async () => {
    const testApp = uniq('app');
    const testLib = uniq('lib');

    await runNxCommandAsync(
      `generate @nx-dotnet/core:app ${testApp} --language="C#" --template="webapi" --skipSwaggerLib`,
    );

    await runNxCommandAsync(
      `generate @nx-dotnet/core:lib ${testLib} --language="C#" --template="classlib"`,
    );

    const output = await runNxCommandAsync(
      `generate @nx-dotnet/core:project-reference ${testApp} ${testLib}`,
    );

    expect(output.stdout).toMatch(/Reference .* added to the project/);
  });

  it('should work with affected', async () => {
    const testApp = uniq('app');
    const testLib = uniq('lib');

    runCommand('git checkout -b "affected-tests"');
    updateFile('package.json', (f) => {
      const json = JSON.parse(f);
      json.dependencies['@nrwl/angular'] = json.devDependencies['nx'];
      return JSON.stringify(json);
    });
    runPackageManagerInstall();

    await runNxCommandAsync(
      `generate @nrwl/angular:app ng-app --style css --routing false --no-interactive`,
      // { cwd: e2eDir, stdio: 'inherit' },
    );

    await runNxCommandAsync(
      `generate @nx-dotnet/core:app ${testApp} --language="C#" --template="webapi" --skipSwaggerLib`,
    );

    await runNxCommandAsync(
      `generate @nx-dotnet/core:lib ${testLib} --language="C#" --template="classlib"`,
    );

    await runNxCommandAsync(
      `generate @nx-dotnet/core:project-reference ${testApp} ${testLib}`,
    );

    const deps = await readDependenciesFromNxDepGraph(join(e2eDir), testApp);
    expect(deps).toContain(testLib);
    runCommand('git checkout main');
  }, 300000);

  describe('nx g app', () => {
    it('should obey dry-run', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skipSwaggerLib --dry-run`,
      );

      expect(() => checkFilesExist(`apps/${app}`)).toThrow();
    });

    it('should generate an app without swagger library', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib`,
      );

      expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
      expect(() =>
        checkFilesExist(`libs/generated/${app}-swaggger/project.json`),
      ).toThrow();
    });

    it('should build and test an app', async () => {
      const app = uniq('app');
      const testProj = `${app}-test`;
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib`,
      );

      await runNxCommandAsync(`build ${app}`);
      await runNxCommandAsync(`test ${testProj}`);

      expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
      expect(() => checkFilesExist(`dist/apps/${app}`)).not.toThrow();
    });

    it('should build an app which depends on a lib', async () => {
      const app = uniq('app');
      const lib = uniq('lib');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib`,
      );
      await runNxCommandAsync(
        `generate @nx-dotnet/core:lib ${lib} --language="C#" --template="classlib"`,
      );
      await runNxCommandAsync(
        `generate @nx-dotnet/core:project-reference --project ${app} --reference ${lib}`,
      );

      await runNxCommandAsync(`build ${app}`);

      expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
      expect(() => checkFilesExist(`dist/apps/${app}`)).not.toThrow();
      expect(() => checkFilesExist(`dist/libs/${lib}`)).not.toThrow();
    });

    it('should update output paths', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib`,
      );
      const configFilePath = findProjectFileInPathSync(
        join(e2eDir, 'apps', app),
      );
      const config = readFileSync(configFilePath).toString();
      const projectXml = new XmlDocument(config);
      const outputPath = projectXml
        .childNamed('PropertyGroup')
        ?.childNamed('OutputPath')?.val as string;
      expect(outputPath).toBeTruthy();
    });

    it('should lint', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --template webapi --language="C#"  --skip-swagger-lib`,
      );
      console.log('LINT TEST PROJECT GENERATED', app);
      const promise = runNxCommandAsync(`lint ${app}`);
      await expect(promise).rejects.toThrow(
        expect.objectContaining({
          message: expect.stringContaining('WHITESPACE'),
        }),
      );
    });
  });

  describe('nx g test', () => {
    it('should add a reference to the target project', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib --test-template="none"`,
      );
      await runNxCommandAsync(
        `generate @nx-dotnet/core:test ${app} --language="C#" --template="nunit"`,
      );

      const config = readFile(
        joinPathFragments(
          'apps',
          `${app}-test`,
          `Proj.${names(app).className}.Test.csproj`,
        ),
      );
      const projectXml = new XmlDocument(config);
      const projectReference = projectXml
        .childrenNamed('ItemGroup')[1]
        ?.childNamed('ProjectReference');

      expect(projectReference).toBeDefined();
    });

    it('should create test project using suffix', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib --test-template="none"`,
      );
      await runNxCommandAsync(
        `generate @nx-dotnet/core:test ${app} --language="C#" --template="nunit" --suffix="integration-tests"`,
      );

      const config = readFile(
        joinPathFragments(
          'apps',
          `${app}-integration-tests`,
          `Proj.${names(app).className}.IntegrationTests.csproj`,
        ),
      );

      expect(config).toBeDefined();
    });
  });

  describe('nx g lib', () => {
    it('should obey dry-run', async () => {
      const lib = uniq('lib');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:lib ${lib} --language="C#" --template="webapi" --skip-swagger-lib --dry-run`,
      );

      expect(() => checkFilesExist(`libs/${lib}`)).toThrow();
    });

    it('should generate an lib', async () => {
      const lib = uniq('lib');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:lib ${lib} --language="C#" --template="classlib"`,
      );

      expect(() => checkFilesExist(`libs/${lib}`)).not.toThrow();
    });
  });

  describe('nx g import-projects', () => {
    it('should import apps, libs, and test', async () => {
      const testApp = uniq('app');
      const testLib = uniq('lib');
      const testAppTest = `${testApp}-test`;
      const appDir = `${e2eDir}/apps/${testApp}`;
      const testAppDir = `${e2eDir}/apps/${testAppTest}`;
      const libDir = `${e2eDir}/libs/${testLib}`;
      ensureDirSync(appDir);
      ensureDirSync(libDir);
      ensureDirSync(testAppDir);
      execSync('dotnet new webapi', { cwd: appDir });
      execSync('dotnet new classlib', { cwd: libDir });
      execSync('dotnet new nunit', { cwd: testAppDir });

      await runNxCommandAsync(`generate @nx-dotnet/core:import-projects`);

      const workspace = new Workspaces(e2eDir).readWorkspaceConfiguration();

      expect(workspace.projects[testApp].targets?.serve).toBeDefined();
      expect(workspace.projects[testApp].targets?.build).toBeDefined();
      expect(workspace.projects[testApp].targets?.lint).toBeDefined();
      expect(workspace.projects[testLib].targets?.serve).not.toBeDefined();
      expect(workspace.projects[testLib].targets?.build).toBeDefined();
      expect(workspace.projects[testLib].targets?.lint).toBeDefined();
      expect(workspace.projects[testAppTest].targets?.build).toBeDefined();
      expect(workspace.projects[testAppTest].targets?.lint).toBeDefined();
      expect(workspace.projects[testAppTest].targets?.test).toBeDefined();

      await runNxCommandAsync(`build ${testApp}`);
      checkFilesExist(`dist/apps/${testApp}`);
    });
  });

  describe('solution handling', () => {
    // For solution handling, defaults fall back to if a file exists.
    // This ensures that the tests are ran in a clean state, without previous
    // test projects interfering with the test.
    beforeAll(() => {
      ensureNxProject('@nx-dotnet/core', 'dist/packages/core');
      initializeGitRepo(e2eDir);
    }, 1500000);

    it("shouldn't create a solution by default if not specified", async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --skip-swagger-lib --template="webapi"`,
      );

      expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
      expect(listFiles('.').filter((x) => x.endsWith('.sln'))).toHaveLength(0);
    });

    it('should create a default solution file if specified as true', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib --solutionFile`,
      );

      expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
      expect(listFiles('.').filter((x) => x.endsWith('.sln'))).toHaveLength(1);
    });

    it('should create specified solution file if specified as string', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --solutionFile="MyCompany.sln"`,
      );

      expect(() =>
        checkFilesExist(`apps/${app}`, `MyCompany.sln`),
      ).not.toThrow();
    });

    it('should add successive projects to default solution file', async () => {
      const app1 = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app1} --language="C#" --skip-swagger-lib --template="webapi" --solutionFile`,
      );

      const app2 = uniq('app2');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app2} --language="C#" --skip-swagger-lib --template="webapi" --solutionFile`,
      );

      const slnFile = readFile('proj.nx-dotnet.sln');

      expect(() => checkFilesExist(`apps/${app1}`)).not.toThrow();
      expect(slnFile).toContain(app1);
      expect(slnFile).toContain(app2);
    });

    it('should add test project to same solution as app project', async () => {
      const app = uniq('app');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib --test-template="xunit" --solutionFile`,
      );

      const slnFile = readFile('proj.nx-dotnet.sln');
      expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
      expect(slnFile).toContain(app);
      expect(slnFile).toContain(app + '-test');
    });
  });

  describe('inferred targets', () => {
    let api: string;
    let projectFolder: string;

    beforeAll(() => {
      api = uniq('api');
      projectFolder = join(e2eDir, 'apps', api);
      ensureDirSync(projectFolder);
      execSync(`dotnet new webapi --language C#`, {
        cwd: projectFolder,
      });
      updateFile('nx.json', (contents) => {
        const json = JSON.parse(contents);
        json.plugins = ['@nx-dotnet/core'];
        return JSON.stringify(json, null, 2);
      });
    });

    it('should work with workspace.json + project.json', () => {
      const relativeProjectPath = joinPathFragments('apps', api);
      writeFileSync(
        join(projectFolder, 'project.json'),
        JSON.stringify({
          root: relativeProjectPath,
        }),
      );
      updateFile('workspace.json', (c) => {
        const json = JSON.parse(c);
        json.projects[api] = relativeProjectPath;
        return JSON.stringify(json, null, 2);
      });
      expect(() => runNxCommand(`build ${api}`)).not.toThrow();
    });

    it('should work without workspace.json or project.json', () => {
      const workspaceJsonContents = readFile('workspace.json');
      unlinkSync(join(e2eDir, 'workspace.json'));

      const projectJsonContents = readFile(
        joinPathFragments('apps', api, 'project.json'),
      );
      unlinkSync(join(projectFolder, 'project.json'));

      expect(() => runNxCommand(`build ${api}`)).not.toThrow();

      writeFileSync(join(e2eDir, 'workspace.json'), workspaceJsonContents);

      writeFileSync(join(projectFolder, 'project.json'), projectJsonContents);
    });
  });

  describe('@nx-dotnet/core:test', () => {
    it('should test with xunit', () => {
      const appProject = uniq('app');
      const testProject = `${appProject}-test`;
      runNxCommand(
        `generate @nx-dotnet/core:app ${appProject} --language="C#" --template="webapi" --skip-swagger-lib --test-runner xunit`,
      );

      expect(() => runNxCommand(`test ${testProject}`)).not.toThrow();

      updateFile(
        `apps/${testProject}/UnitTest1.cs`,
        `using Xunit;

namespace Proj.${names(appProject).className}.Test;

public class UnitTest1
{
    // This test should fail, as the e2e test is checking for test failures.
    [Fact]
    public void Test1()
    {
      Assert.Equal(1, 2)
    }
}`,
      );

      expect(() => runNxCommand(`test ${testProject}`)).toThrow();
    });

    it('should work with watch', async () => {
      const appProject = uniq('app');
      const testProject = `${appProject}-test`;
      runNxCommand(
        `generate @nx-dotnet/core:app ${appProject} --language="C#" --template="webapi" --skip-swagger-lib --test-runner xunit`,
      );
      const p = runCommandUntil(
        `test ${testProject} --watch`,
        (output) =>
          output.includes(
            'Waiting for a file to change before restarting dotnet...',
          ),
        { kill: true },
      );
      await expect(p).resolves.not.toThrow();
    });
  });

  describe('swagger integration', () => {
    it('should generate swagger project for webapi', async () => {
      const api = uniq('api');
      await runNxCommandAsync(
        `generate @nx-dotnet/core:app ${api} --language="C#" --template="webapi"`,
      );

      expect(() => checkFilesExist(`apps/${api}`)).not.toThrow();
      expect(() =>
        checkFilesExist(`libs/generated/${api}-swagger`),
      ).not.toThrow();
      expect(() => runNxCommand(`swagger ${api}`)).not.toThrow();
      expect(() =>
        checkFilesExist(`libs/generated/${api}-swagger/swagger.json`),
      ).not.toThrow();
    });
  });
});