fs#appendFileSync TypeScript Examples

The following examples show how to use fs#appendFileSync. 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: addEnv.ts    From setup-cpp with Apache License 2.0 6 votes vote down vote up
async function addEnvSystem(name: string, valGiven: string | undefined) {
  const val = valGiven ?? ""
  switch (process.platform) {
    case "win32": {
      // We do not use `execa.sync(`setx PATH "${path};%PATH%"`)` because of its character limit
      await execPowershell(`[Environment]::SetEnvironmentVariable('${name}', '${val}', "User")`)
      info(`${name}='${val}' was set in the environment.`)
      return
    }
    case "linux":
    case "darwin": {
      setupCppInProfile()
      appendFileSync(cpprc_path, `\nexport ${name}="${val}"\n`)
      info(`${name}="${val}" was added to "${cpprc_path}`)
      return
    }
    default: {
      // fall through shell path modification
    }
  }
  process.env[name] = val
}
Example #2
Source File: addEnv.ts    From setup-cpp with Apache License 2.0 6 votes vote down vote up
async function addPathSystem(path: string) {
  switch (process.platform) {
    case "win32": {
      // We do not use `execa.sync(`setx PATH "${path};%PATH%"`)` because of its character limit and also because %PATH% is different for user and system
      await execPowershell(
        `$USER_PATH=([Environment]::GetEnvironmentVariable("PATH", "User")); [Environment]::SetEnvironmentVariable("PATH", "${path};$USER_PATH", "User")`
      )
      info(`${path} was added to the PATH.`)
      return
    }
    case "linux":
    case "darwin": {
      setupCppInProfile()
      appendFileSync(cpprc_path, `\nexport PATH=${path}:$PATH\n`)
      info(`${path} was added to "${cpprc_path}"`)
      return
    }
    default: {
      return
    }
  }
}
Example #3
Source File: addEnv.ts    From setup-cpp with Apache License 2.0 6 votes vote down vote up
/// handles adding conditions to source .cpprc file from .bashrc and .profile
export function setupCppInProfile() {
  if (setupCppInProfile_called) {
    return
  }

  // a variable that prevents source_cpprc from being called from .bashrc and .profile
  const source_cpprc_str = "export SOURCE_CPPRC=0"

  if (existsSync(cpprc_path)) {
    const cpprc_content = readFileSync(cpprc_path, "utf8")
    if (cpprc_content.includes(source_cpprc_str)) {
      // already executed setupCppInProfile
      return
    }
  }

  appendFileSync(cpprc_path, `\n${source_cpprc_str}\n`)
  info(`Added ${source_cpprc_str} to ${cpprc_path}`)

  const source_cpprc_string = `\n# source .cpprc if SOURCE_CPPRC is not set to 0\nif [[ "$SOURCE_CPPRC" != 0 && -f "${cpprc_path}" ]]; then source "${cpprc_path}"; fi\n`

  try {
    // source cpprc in .profile
    const profile_path = untildify(".profile")
    appendFileSync(profile_path, source_cpprc_string)
    info(`${source_cpprc_string} was added to ${profile_path}`)

    // source cpprc in .bashrc too
    const bashrc_path = untildify(".bashrc")
    appendFileSync(bashrc_path, source_cpprc_string)
    info(`${source_cpprc_string} was added to ${bashrc_path}`)
  } catch (err) {
    warning(`Failed to add ${source_cpprc_string} to .profile or .bashrc. You should add it manually: ${err}`)
  }

  setupCppInProfile_called = true
}
Example #4
Source File: setupAptPack.ts    From setup-cpp with Apache License 2.0 6 votes vote down vote up
export function updateAptAlternatives(name: string, path: string) {
  if (isGitHubCI()) {
    return execSudo("update-alternatives", ["--install", `/usr/bin/${name}`, name, path, "40"])
  } else {
    setupCppInProfile()
    return appendFileSync(
      cpprc_path,
      `\nif [ $UID -eq 0 ]; then update-alternatives --install /usr/bin/${name} ${name} ${path} 40; fi\n`
    )
  }
}
Example #5
Source File: angular.specs.ts    From cli with Apache License 2.0 4 votes vote down vote up
// TODO CDX-804: Enable the tests back
describe('ui:create:angular', () => {
  let browser: Browser;
  const processManagers: ProcessManager[] = [];
  let page: Page;
  const oldEnv = process.env;
  const parentDir = 'angular';
  const projectName = `${process.env.TEST_RUN_ID}-${parentDir}-project`;
  const projectPath = join(getUIProjectPath(), parentDir, projectName);
  let clientPort: number;
  let serverPort: number;
  const angularJsonPath = join(projectPath, 'angular.json');

  const searchPageEndpoint = () => `http://localhost:${clientPort}`;

  const tokenServerEndpoint = () => `http://localhost:${serverPort}/token`;

  const setCustomTokenEndpoint = (endpoint: string) => {
    const webAppEnvironment = resolve(
      projectPath,
      'src',
      'environments',
      'environment.ts'
    );
    const portNumberMatcher = /customTokenEndpoint:\s?.*$/m;
    const appEnvironmentFile = readFileSync(webAppEnvironment, 'utf-8');
    const subst = `customTokenEndpoint: '${endpoint}',`;
    const updatedEnvironment = appEnvironmentFile.replace(
      portNumberMatcher,
      subst
    );

    writeFileSync(webAppEnvironment, updatedEnvironment);
  };

  const resetCustomTokenEndpoint = () => setCustomTokenEndpoint('');

  const forceTokenServerPort = (port: number) => {
    const pathToEnv = resolve(projectPath, 'server', '.env');
    const environment = parse(readFileSync(pathToEnv, {encoding: 'utf-8'}));

    const updatedEnvironment = {
      ...environment,
      SERVER_PORT: port,
    };

    truncateSync(pathToEnv);
    for (const [key, value] of Object.entries(updatedEnvironment)) {
      appendFileSync(pathToEnv, `${key}=${value}${EOL}`);
    }
  };

  const forceAppPort = (port: number) => {
    const angularJSON = JSON.parse(readFileSync(angularJsonPath, 'utf-8'));

    const serve = angularJSON.projects[projectName].architect.serve;
    if (!serve.options) {
      serve.options = {};
    }
    serve.options.port = port;

    writeFileSync(angularJsonPath, JSON.stringify(angularJSON, undefined, 2));
  };

  const getAllocatedPorts = () => {
    const envVariables = parse(
      readFileSync(getPathToEnvFile(join(projectPath, 'server')))
    );

    if (!envVariables) {
      throw new Error('Unable to load project environment variables');
    }

    serverPort = parseInt(envVariables.SERVER_PORT);

    const angularJSON = JSON.parse(readFileSync(angularJsonPath, 'utf-8'));
    const servePort =
      angularJSON.projects[projectName].architect.serve.options.port;
    clientPort = parseInt(servePort);

    return [clientPort, serverPort];
  };

  const buildApplication = async (processManager: ProcessManager) => {
    const buildTerminal = await setupUIProject(
      processManager,
      'ui:create:angular',
      projectName,
      {
        flags: ['--defaults'],
        projectDir: projectPath,
      }
    );

    const buildTerminalExitPromise = Promise.race([
      buildTerminal.when('exit').on('process').do().once(),
      buildTerminal
        .when(/Happy hacking!/)
        .on('stdout')
        .do()
        .once(),
    ]);

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

  const startApplication = async (
    processManager: ProcessManager,
    debugName = 'angular-server'
  ) => {
    const args = [...npm(), 'run', 'start'];
    const serverTerminal = new Terminal(
      args.shift()!,
      args,
      {
        cwd: projectPath,
      },
      processManager,
      debugName
    );
    return serverTerminal;
  };

  const waitForAppRunning = (appTerminal: Terminal) =>
    appTerminal
      .when(/Compiled successfully/)
      .on('stdout')
      .do()
      .once();

  beforeAll(async () => {
    await loginWithApiKey(
      process.env.PLATFORM_API_KEY!,
      process.env.ORG_ID!,
      process.env.PLATFORM_ENV!
    );
    const buildProcessManager = new ProcessManager();
    processManagers.push(buildProcessManager);
    browser = await getNewBrowser();
    await buildApplication(buildProcessManager);
    await buildProcessManager.killAllProcesses();
  }, 20 * 60e3);

  beforeEach(async () => {
    jest.resetModules();
    process.env = {...oldEnv};
    page = await openNewPage(browser, page);
  });

  afterEach(async () => {
    await captureScreenshots(browser);
  });

  afterAll(async () => {
    process.env = oldEnv;
    await browser.close();
    await Promise.all(
      processManagers.map((manager) => manager.killAllProcesses())
    );
  });

  describe('when the project is configured correctly', () => {
    let serverProcessManager: ProcessManager;
    let interceptedRequests: HTTPRequest[] = [];
    let consoleInterceptor: BrowserConsoleInterceptor;
    const searchboxSelector = 'app-search-page app-search-box input';

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      const appTerminal = await startApplication(
        serverProcessManager,
        'angular-server-valid'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 15 * 60e3);

    beforeEach(async () => {
      consoleInterceptor = new BrowserConsoleInterceptor(page, projectName);
      await consoleInterceptor.startSession();

      page.on('request', (request: HTTPRequest) => {
        interceptedRequests.push(request);
      });
    });

    afterEach(async () => {
      page.removeAllListeners('request');
      interceptedRequests = [];
      await consoleInterceptor.endSession();
    });

    afterAll(async () => {
      await undoCommit(serverProcessManager, projectPath, projectName);
      await serverProcessManager.killAllProcesses();
    }, 5 * 60e3);
    // TODO CDX-1017: Remove skip
    it.skip(
      'should not contain console errors nor warnings',
      async () => {
        await page.goto(searchPageEndpoint(), {
          waitUntil: 'networkidle2',
        });

        expect(consoleInterceptor.interceptedMessages).toEqual([]);
      },
      5 * 60e3
    );

    it('should contain a search page section', async () => {
      await page.goto(searchPageEndpoint(), {
        waitUntil: 'networkidle2',
      });
      await page.waitForSelector(searchboxSelector);

      expect(await page.$('app-search-page')).not.toBeNull();
    }, 60e3);

    it('should retrieve the search token on the page load', async () => {
      const tokenResponseListener = page.waitForResponse(tokenServerEndpoint());

      page.goto(searchPageEndpoint());
      await page.waitForSelector(searchboxSelector);

      expect(
        JSON.parse(await (await tokenResponseListener).text())
      ).toMatchObject({
        token: expect.stringMatching(jwtTokenPattern),
      });
    }, 60e3);

    it('should send a search query when the page is loaded', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      await page.waitForSelector(searchboxSelector);

      expect(interceptedRequests.some(isSearchRequestOrResponse)).toBeTruthy();
    });

    it('should send a search query on searchbox submit', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      await page.waitForSelector(searchboxSelector);

      interceptedRequests = [];

      await page.focus(searchboxSelector);
      await page.keyboard.type('my query');
      await page.keyboard.press('Enter');

      await retry(async () => {
        expect(
          interceptedRequests.some(isSearchRequestOrResponse)
        ).toBeTruthy();
      });
    }, 60e3);

    it('should be commited without lint-stage errors', async () => {
      const eslintErrorSpy = jest.fn();

      await commitProject(
        serverProcessManager,
        projectPath,
        projectName,
        eslintErrorSpy
      );

      expect(eslintErrorSpy).not.toBeCalled();
    }, 60e3);
  });

  describe('when the .env file is missing', () => {
    let serverProcessManager: ProcessManager;

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      deactivateEnvironmentFile(join(projectPath, 'server'));
    });

    afterAll(async () => {
      restoreEnvironmentFile(join(projectPath, 'server'));
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it(
      'should not start the application',
      async () => {
        const missingEnvErrorSpy = jest.fn();

        const appTerminal = await startApplication(
          serverProcessManager,
          'angular-server-missing-env'
        );

        await appTerminal
          .when(/\.env file not found in the project root/)
          .on('stderr')
          .do(missingEnvErrorSpy)
          .once();

        expect(missingEnvErrorSpy).toHaveBeenCalled();
      },
      2 * 60e3
    );
  });

  describe('when the required environment variables are missing', () => {
    let serverProcessManager: ProcessManager;
    let envFileContent = '';

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      envFileContent = flushEnvFile(join(projectPath, 'server'));
      const appTerminal = await startApplication(
        serverProcessManager,
        'angular-server-invalid'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      overwriteEnvFile(join(projectPath, 'server'), envFileContent);
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it('should redirect the user to an error page', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      expect(page.url()).toEqual(`${searchPageEndpoint()}/error`);
    });
  });

  describe('when the a custom token Endpoint is specified', () => {
    const customTokenEndpoint = 'http://dummyendpoint.com/some-kind-of-path';
    let serverProcessManager: ProcessManager;
    let interceptedRequests: HTTPRequest[] = [];

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      setCustomTokenEndpoint(customTokenEndpoint);

      const appTerminal = await startApplication(
        serverProcessManager,
        'angular-server-port-test'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      await serverProcessManager.killAllProcesses();
      resetCustomTokenEndpoint();
    }, 30e3);

    beforeEach(async () => {
      page.on('request', (request: HTTPRequest) => {
        interceptedRequests.push(request);
      });
    });

    afterEach(async () => {
      page.removeAllListeners('request');
      interceptedRequests = [];
    });

    it('should use the custom token endpoint', async () => {
      page.goto(searchPageEndpoint());

      await retry(async () => {
        expect(
          interceptedRequests.some(
            (request: HTTPRequest) => request.url() === customTokenEndpoint
          )
        ).toBeTruthy();
      });
    }, 10e3);
  });

  describe('when the ports are busy', () => {
    const dummyServers: DummyServer[] = [];
    let serverProcessManager: ProcessManager;
    let usedClientPort: number;
    let usedServerPort: number;

    beforeAll(async () => {
      usedClientPort = await getPort();
      usedServerPort = await getPort();
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      forceAppPort(usedClientPort);
      forceTokenServerPort(usedServerPort);

      dummyServers.push(
        new DummyServer(usedClientPort),
        new DummyServer(usedServerPort)
      );

      const appTerminal = await startApplication(
        serverProcessManager,
        'angular-server-port-test'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      await Promise.all(dummyServers.map((server) => server.close()));
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it('should allocate a new port for the application', async () => {
      expect(clientPort).not.toEqual(usedClientPort);
    });

    it('should not use an undefined port for application', async () => {
      expect(clientPort).not.toBeUndefined();
    });

    it('should allocate a new port for the token server', async () => {
      expect(serverPort).not.toEqual(usedServerPort);
    });

    it('should not use an undefined port for token server', async () => {
      expect(serverPort).not.toBeUndefined();
    });

    it('should run the application on a new port', async () => {
      await expect(
        page.goto(searchPageEndpoint(), {waitUntil: 'load'})
      ).resolves.not.toThrow();
    });

    it('should run the server on a new port', async () => {
      const tokenRequest = await axios.get(tokenServerEndpoint());
      expect(tokenRequest.data.token).toMatch(jwtTokenPattern);
    });
  });
});
Example #6
Source File: react.specs.ts    From cli with Apache License 2.0 4 votes vote down vote up
describe('ui:create:react', () => {
  let browser: Browser;
  const processManagers: ProcessManager[] = [];
  let page: Page;
  const oldEnv = process.env;
  const parentDir = 'react';
  const projectName = `${process.env.TEST_RUN_ID}-react-project`;
  const projectPath = join(getUIProjectPath(), parentDir, projectName);
  let clientPort: number;
  let serverPort: number;

  const searchPageEndpoint = () => `http://localhost:${clientPort}`;

  const tokenServerEndpoint = () => `http://localhost:${serverPort}/token`;

  const waitForAppRunning = (appTerminal: Terminal) =>
    appTerminal
      .when(/You can now view .*-react-project in the browser/)
      .on('stdout')
      .do()
      .once();

  const forceApplicationPorts = (clientPort: number, serverPort: number) => {
    const envPath = getPathToEnvFile(projectPath);
    const environment = parse(readFileSync(envPath, {encoding: 'utf-8'}));

    const updatedEnvironment = {
      ...environment,
      PORT: clientPort,
      REACT_APP_SERVER_PORT: serverPort,
    };
    truncateSync(envPath);
    for (const [key, value] of Object.entries(updatedEnvironment)) {
      appendFileSync(envPath, `${key}=${value}${EOL}`);
    }
  };

  const getAllocatedPorts = () => {
    const envVariables = parse(
      readFileSync(getPathToEnvFile(projectPath), {encoding: 'utf-8'})
    );

    if (!envVariables) {
      throw new Error('Unable to load project environment variables');
    }

    clientPort = parseInt(envVariables.PORT);
    serverPort = parseInt(envVariables.REACT_APP_SERVER_PORT);

    return [clientPort, serverPort];
  };

  const buildApplication = async (processManager: ProcessManager) => {
    const buildTerminal = await setupUIProject(
      processManager,
      'ui:create:react',
      projectName,
      {projectDir: projectPath}
    );

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

  const startApplication = async (
    processManager: ProcessManager,
    debugName = 'react-server'
  ) => {
    const args = [...npm(), 'run', 'start'];
    const serverTerminal = new Terminal(
      args.shift()!,
      args,
      {
        cwd: projectPath,
      },
      processManager,
      debugName
    );
    return serverTerminal;
  };

  beforeAll(async () => {
    await loginWithApiKey(
      process.env.PLATFORM_API_KEY!,
      process.env.ORG_ID!,
      process.env.PLATFORM_ENV!
    );
    const buildProcessManager = new ProcessManager();
    processManagers.push(buildProcessManager);
    browser = await getNewBrowser();
    await buildApplication(buildProcessManager);
    await buildProcessManager.killAllProcesses();
  }, 15 * 60e3);

  beforeEach(async () => {
    jest.resetModules();
    process.env = {...oldEnv};
    page = await openNewPage(browser, page);
  });

  afterEach(async () => {
    await captureScreenshots(browser);
  });

  afterAll(async () => {
    process.env = oldEnv;
    await browser.close();
    await Promise.all(
      processManagers.map((manager) => manager.killAllProcesses())
    );
  });

  describe('when the project is configured correctly', () => {
    let serverProcessManager: ProcessManager;
    let interceptedRequests: HTTPRequest[] = [];
    let consoleInterceptor: BrowserConsoleInterceptor;
    const searchboxSelector = 'div.App .MuiAutocomplete-root input';

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      const appTerminal = await startApplication(
        serverProcessManager,
        'react-server-valid'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 10 * 60e3);

    beforeEach(async () => {
      consoleInterceptor = new BrowserConsoleInterceptor(page, projectPath);
      await consoleInterceptor.startSession();

      page.on('request', (request: HTTPRequest) => {
        interceptedRequests.push(request);
      });
    });

    afterEach(async () => {
      page.removeAllListeners('request');
      interceptedRequests = [];
      await consoleInterceptor.endSession();
    });

    afterAll(async () => {
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    // TODO CDX-1017: Remove skip
    it.skip(
      'should not contain console errors nor warnings',
      async () => {
        await page.goto(searchPageEndpoint(), {
          waitUntil: 'networkidle2',
        });

        expect(consoleInterceptor.interceptedMessages).toEqual([]);
      },
      5 * 60e3
    );

    it('should contain a search page section', async () => {
      await page.goto(searchPageEndpoint(), {
        waitUntil: 'networkidle2',
      });
      await page.waitForSelector(searchboxSelector);

      expect(await page.$('div.App')).not.toBeNull();
    });

    it('should retrieve the search token on the page load', async () => {
      const tokenResponseListener = page.waitForResponse(tokenServerEndpoint());

      page.goto(searchPageEndpoint());
      await page.waitForSelector(searchboxSelector);

      expect(
        JSON.parse(await (await tokenResponseListener).text())
      ).toMatchObject({
        token: expect.stringMatching(jwtTokenPattern),
      });
    });

    it('should send a search query when the page is loaded', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      await page.waitForSelector(searchboxSelector);

      expect(interceptedRequests.some(isSearchRequestOrResponse)).toBeTruthy();
    });

    it('should send a search query on searchbox submit', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      await page.waitForSelector(searchboxSelector);

      interceptedRequests = [];

      await page.focus(searchboxSelector);
      await page.keyboard.type('my query');
      await page.keyboard.press('Enter');

      await retry(async () => {
        expect(
          interceptedRequests.some(isSearchRequestOrResponse)
        ).toBeTruthy();
      });
    });
    it('should have a clean working directory', async () => {
      const gitDirtyWorkingTreeSpy = jest.fn();

      await isDirectoryClean(
        serverProcessManager,
        projectPath,
        projectName,
        gitDirtyWorkingTreeSpy
      );

      expect(gitDirtyWorkingTreeSpy).not.toBeCalled();
    }, 10e3);
  });

  describe('when the .env file is missing', () => {
    let serverProcessManager: ProcessManager;

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      deactivateEnvironmentFile(projectPath);
    });

    afterAll(async () => {
      restoreEnvironmentFile(projectPath);
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it(
      'should not start the application',
      async () => {
        const missingEnvErrorSpy = jest.fn();

        const appTerminal = await startApplication(
          serverProcessManager,
          'react-server-missing-env'
        );

        await appTerminal
          .when(/\.env file not found in the project root/)
          .on('stderr')
          .do(missingEnvErrorSpy)
          .once();

        expect(missingEnvErrorSpy).toHaveBeenCalled();
      },
      10 * 60e3
    );
  });

  describe('when required environment variables are not defined', () => {
    let serverProcessManager: ProcessManager;
    let envFileContent = '';
    const errorMessageSelector = 'div.container';

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      envFileContent = flushEnvFile(projectPath);
      overwriteEnvFile(projectPath, 'GENERATE_SOURCEMAP=false'); // TODO: CDX-737: fix exponential-backoff compilation warnings
      const appTerminal = await startApplication(
        serverProcessManager,
        'react-server-invalid'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      overwriteEnvFile(projectPath, envFileContent);
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it('should redirect the user to an error page', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      const pageErrorMessage = await page.$eval(
        errorMessageSelector,
        (el) => el.textContent
      );
      expect(pageErrorMessage).toContain(
        'You should have a valid .env file at the root of this project'
      );
    });
  });

  describe('when the ports are manually specified', () => {
    let serverProcessManager: ProcessManager;
    let hardCodedClientPort: number;
    let hardCodedServerPort: number;

    beforeAll(async () => {
      hardCodedClientPort = await getPort();
      hardCodedServerPort = await getPort();
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      forceApplicationPorts(hardCodedClientPort, hardCodedServerPort);

      const appTerminal = await startApplication(
        serverProcessManager,
        'react-server-port-test'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it('should run the application on the specified port', async () => {
      expect(clientPort).toEqual(hardCodedClientPort);
    });

    it('should run the token server on the specified port', async () => {
      expect(serverPort).toEqual(hardCodedServerPort);
    });
  });

  describe('when the ports are busy', () => {
    const dummyServers: DummyServer[] = [];
    let serverProcessManager: ProcessManager;
    let usedClientPort: number;
    let usedServerPort: number;

    beforeAll(async () => {
      usedClientPort = await getPort();
      usedServerPort = await getPort();
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      forceApplicationPorts(usedClientPort, usedServerPort);

      dummyServers.push(
        new DummyServer(usedClientPort),
        new DummyServer(usedServerPort)
      );

      const appTerminal = await startApplication(
        serverProcessManager,
        'react-server-port-test'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      await Promise.all(dummyServers.map((server) => server.close()));
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it('should allocate a new port for the application', async () => {
      expect(clientPort).not.toEqual(usedClientPort);
    });

    it('should not use an undefined port for application', async () => {
      expect(clientPort).not.toBeUndefined();
    });

    it('should allocate a new port for the token server', async () => {
      expect(serverPort).not.toEqual(usedServerPort);
    });

    it('should not use an undefined port for token server', async () => {
      expect(serverPort).not.toBeUndefined();
    });

    it('should run the application on a new port', async () => {
      await expect(
        page.goto(searchPageEndpoint(), {waitUntil: 'load'})
      ).resolves.not.toThrow();
    });

    it('should run the server on a new port', async () => {
      const tokenRequest = await axios.get(tokenServerEndpoint());
      expect(tokenRequest.data.token).toMatch(jwtTokenPattern);
    });
  });
});
Example #7
Source File: vue.specs.ts    From cli with Apache License 2.0 4 votes vote down vote up
describe('ui:create:vue', () => {
  let browser: Browser;
  const processManagers: ProcessManager[] = [];
  let page: Page;
  const oldEnv = process.env;
  const parentDir = 'vue';
  const projectName = `${process.env.TEST_RUN_ID}-${parentDir}-project`;
  const projectPath = join(getUIProjectPath(), parentDir, projectName);
  let clientPort: number;
  let serverPort: number;

  const searchPageEndpoint = () => `http://localhost:${clientPort}`;

  const tokenServerEndpoint = () => `http://localhost:${serverPort}/token`;

  const forceApplicationPorts = (clientPort: number, serverPort: number) => {
    const envPath = getPathToEnvFile(projectPath);
    const environment = parse(readFileSync(envPath, {encoding: 'utf-8'}));

    const updatedEnvironment = {
      ...environment,
      PORT: clientPort,
      VUE_APP_SERVER_PORT: serverPort,
    };
    truncateSync(envPath);
    for (const [key, value] of Object.entries(updatedEnvironment)) {
      appendFileSync(envPath, `${key}=${value}${EOL}`);
    }
  };

  const waitForAppRunning = (appTerminal: Terminal) =>
    appTerminal
      .when(/App running at:/)
      .on('stdout')
      .do()
      .once();

  const getAllocatedPorts = () => {
    const envVariables = parse(
      readFileSync(getPathToEnvFile(projectPath), {encoding: 'utf-8'})
    );

    if (!envVariables) {
      throw new Error('Unable to load project environment variables');
    }

    clientPort = parseInt(envVariables.PORT);
    serverPort = parseInt(envVariables.VUE_APP_SERVER_PORT);

    return [clientPort, serverPort];
  };

  const buildApplication = async (processManager: ProcessManager) => {
    const buildTerminal = await setupUIProject(
      processManager,
      'ui:create:vue',
      projectName,
      {projectDir: projectPath}
    );

    const buildTerminalExitPromise = Promise.race([
      buildTerminal.when('exit').on('process').do().once(),
      buildTerminal
        .when(/Happy hacking!/)
        .on('stdout')
        .do()
        .once(),
    ]);

    await buildTerminal
      .when(isGenericYesNoPrompt)
      .on('stdout')
      .do(answerPrompt(`y${EOL}`))
      .until(buildTerminalExitPromise);

    await buildTerminalExitPromise;
  };

  const startApplication = async (
    processManager: ProcessManager,
    debugName = 'vue-server'
  ) => {
    const args = [...npm(), 'run', 'start'];

    const serverTerminal = new Terminal(
      args.shift()!,
      args,
      {
        cwd: projectPath,
      },
      processManager,
      debugName
    );
    return serverTerminal;
  };

  beforeAll(async () => {
    await loginWithApiKey(
      process.env.PLATFORM_API_KEY!,
      process.env.ORG_ID!,
      process.env.PLATFORM_ENV!
    );
    const buildProcessManager = new ProcessManager();
    processManagers.push(buildProcessManager);
    browser = await getNewBrowser();
    await buildApplication(buildProcessManager);
    await buildProcessManager.killAllProcesses();
  }, 15 * 60e3);

  beforeEach(async () => {
    jest.resetModules();
    process.env = {...oldEnv};
    page = await openNewPage(browser, page);
  });

  afterEach(async () => {
    await captureScreenshots(browser);
  });

  afterAll(async () => {
    process.env = oldEnv;
    await browser.close();
    await Promise.all(
      processManagers.map((manager) => manager.killAllProcesses())
    );
  });

  describe('when the project is configured correctly', () => {
    let serverProcessManager: ProcessManager;
    let interceptedRequests: HTTPRequest[] = [];
    let consoleInterceptor: BrowserConsoleInterceptor;
    const searchboxSelector = '#search-page .autocomplete input';

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      const appTerminal = await startApplication(
        serverProcessManager,
        'vue-server-valid'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    beforeEach(async () => {
      consoleInterceptor = new BrowserConsoleInterceptor(page, projectName);
      await consoleInterceptor.startSession();

      page.on('request', (request: HTTPRequest) => {
        interceptedRequests.push(request);
      });
    });

    afterEach(async () => {
      page.removeAllListeners('request');
      interceptedRequests = [];
      await consoleInterceptor.endSession();
    });

    afterAll(async () => {
      await undoCommit(serverProcessManager, projectPath, projectName);
      await serverProcessManager.killAllProcesses();
    }, 5 * 60e3);
    // TODO CDX-1017: Remove skip
    it.skip('should not contain console errors nor warnings', async () => {
      await page.goto(searchPageEndpoint(), {
        waitUntil: 'networkidle2',
      });

      expect(consoleInterceptor.interceptedMessages).toEqual([]);
    }, 60e3);

    it('should contain a search page section', async () => {
      await page.goto(searchPageEndpoint(), {
        waitUntil: 'networkidle2',
      });
      await page.waitForSelector(searchboxSelector);

      expect(await page.$('#search-page')).not.toBeNull();
    }, 60e3);

    it('should retrieve the search token on the page load', async () => {
      const tokenResponseListener = page.waitForResponse(tokenServerEndpoint());

      page.goto(searchPageEndpoint());
      await page.waitForSelector(searchboxSelector);

      expect(
        JSON.parse(await (await tokenResponseListener).text())
      ).toMatchObject({
        token: expect.stringMatching(jwtTokenPattern),
      });
    }, 60e3);

    it('should send a search query when the page is loaded', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      await page.waitForSelector(searchboxSelector);

      expect(interceptedRequests.some(isSearchRequestOrResponse)).toBeTruthy();
    }, 60e3);

    it('should send a search query on searchbox submit', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      await page.waitForSelector(searchboxSelector);

      interceptedRequests = [];

      await page.focus(searchboxSelector);
      await page.keyboard.type('my query');
      await page.keyboard.press('Enter');

      await retry(async () => {
        expect(
          interceptedRequests.some(isSearchRequestOrResponse)
        ).toBeTruthy();
      });
    }, 60e3);

    it('should be commited without lint-stage errors', async () => {
      const eslintErrorSpy = jest.fn();

      await commitProject(
        serverProcessManager,
        projectPath,
        projectName,
        eslintErrorSpy
      );

      expect(eslintErrorSpy).not.toBeCalled();
    }, 10e3);
  });

  describe('when starting the server', () => {
    let serverProcessManager: ProcessManager;

    beforeEach(() => {
      serverProcessManager = new ProcessManager();
    });

    afterEach(async () => {
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it(
      'should not have any ESLint warning or error',
      async () => {
        const serverTerminal = await startApplication(
          serverProcessManager,
          'vue-server-eslint'
        );
        const eslintErrorSpy = jest.fn();

        await serverTerminal
          .when(/✖ \d+ problems \(\d+ errors, \d+ warnings\)/)
          .on('stdout')
          .do(eslintErrorSpy)
          .until(waitForAppRunning(serverTerminal));

        expect(eslintErrorSpy).not.toBeCalled();
      },
      5 * 60e3
    );
  });

  describe('when the .env file is missing', () => {
    let serverProcessManager: ProcessManager;

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      deactivateEnvironmentFile(projectPath);
    });

    afterAll(async () => {
      await serverProcessManager.killAllProcesses();
      restoreEnvironmentFile(projectPath);
    }, 30e3);

    it(
      'should not start the application',
      async () => {
        const missingEnvErrorSpy = jest.fn();

        const appTerminal = await startApplication(
          serverProcessManager,
          'vue-server-missing-env'
        );

        await appTerminal
          .when(/\.env file not found in the project root/)
          .on('stderr')
          .do(missingEnvErrorSpy)
          .once();

        expect(missingEnvErrorSpy).toHaveBeenCalled();
      },
      2 * 60e3
    );
  });

  describe('when required environment variables are not defined', () => {
    let serverProcessManager: ProcessManager;
    let envFileContent = '';

    beforeAll(async () => {
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      envFileContent = flushEnvFile(projectPath);
      const appTerminal = await startApplication(
        serverProcessManager,
        'vue-server-invalid'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      overwriteEnvFile(projectPath, envFileContent);
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it('should redirect the user to an error page', async () => {
      await page.goto(searchPageEndpoint(), {waitUntil: 'networkidle2'});
      expect(page.url()).toEqual(`${searchPageEndpoint()}/error`);
    }, 60e3);
  });

  describe('when the ports are manually specified', () => {
    let serverProcessManager: ProcessManager;
    let hardCodedClientPort: number;
    let hardCodedServerPort: number;

    beforeAll(async () => {
      hardCodedClientPort = await getPort();
      hardCodedServerPort = await getPort();
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      forceApplicationPorts(hardCodedClientPort, hardCodedServerPort);

      const appTerminal = await startApplication(
        serverProcessManager,
        'vue-server-port-test'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it('should run the application on the specified port', async () => {
      expect(clientPort).toEqual(hardCodedClientPort);
    }, 60e3);

    it('should run the token server on the specified port', async () => {
      expect(serverPort).toEqual(hardCodedServerPort);
    }, 60e3);
  });

  describe('when the ports are busy', () => {
    const dummyServers: DummyServer[] = [];
    let serverProcessManager: ProcessManager;
    let usedClientPort: number;
    let usedServerPort: number;

    beforeAll(async () => {
      usedClientPort = await getPort();
      usedServerPort = await getPort();
      serverProcessManager = new ProcessManager();
      processManagers.push(serverProcessManager);
      forceApplicationPorts(usedClientPort, usedServerPort);

      dummyServers.push(
        new DummyServer(usedClientPort),
        new DummyServer(usedServerPort)
      );

      const appTerminal = await startApplication(
        serverProcessManager,
        'vue-server-port-test'
      );
      await waitForAppRunning(appTerminal);
      [clientPort, serverPort] = getAllocatedPorts();
    }, 2 * 60e3);

    afterAll(async () => {
      await Promise.all(dummyServers.map((server) => server.close()));
      await serverProcessManager.killAllProcesses();
    }, 30e3);

    it('should allocate a new port for the application', async () => {
      expect(clientPort).not.toEqual(usedClientPort);
    });

    it('should not use an undefined port for application', async () => {
      expect(clientPort).not.toBeUndefined();
    });

    it('should allocate a new port for the token server', async () => {
      expect(serverPort).not.toEqual(usedServerPort);
    });

    it('should not use an undefined port for token server', async () => {
      expect(serverPort).not.toBeUndefined();
    });

    it('should run the application on a new port', async () => {
      await expect(
        page.goto(searchPageEndpoint(), {waitUntil: 'load'})
      ).resolves.not.toThrow();
    });

    it('should run the server on a new port', async () => {
      const tokenRequest = await axios.get(tokenServerEndpoint());
      expect(tokenRequest.data.token).toMatch(jwtTokenPattern);
    });
  });

  it.todo('should create a Vue.js project with a custom preset');
});
Example #8
Source File: descriptor.test.ts    From nouns-monorepo with GNU General Public License v3.0 4 votes vote down vote up
describe('NounsDescriptor', () => {
  let nounsDescriptor: NounsDescriptor;
  let snapshotId: number;

  const part: LongestPart = {
    length: 0,
    index: 0,
  };
  const longest: Record<string, LongestPart> = {
    bodies: part,
    accessories: part,
    heads: part,
    glasses: part,
  };

  before(async () => {
    nounsDescriptor = await deployNounsDescriptor();

    for (const [l, layer] of Object.entries(ImageData.images)) {
      for (const [i, item] of layer.entries()) {
        if (item.data.length > longest[l].length) {
          longest[l] = {
            length: item.data.length,
            index: i,
          };
        }
      }
    }

    await populateDescriptor(nounsDescriptor);
  });

  beforeEach(async () => {
    snapshotId = await ethers.provider.send('evm_snapshot', []);
  });

  afterEach(async () => {
    await ethers.provider.send('evm_revert', [snapshotId]);
  });

  it('should generate valid token uri metadata when data uris are disabled', async () => {
    const BASE_URI = 'https://api.nouns.wtf/metadata/';

    await nounsDescriptor.setBaseURI(BASE_URI);
    await nounsDescriptor.toggleDataURIEnabled();

    const tokenUri = await nounsDescriptor.tokenURI(0, {
      background: 0,
      body: longest.bodies.index,
      accessory: longest.accessories.index,
      head: longest.heads.index,
      glasses: longest.glasses.index,
    });
    expect(tokenUri).to.equal(`${BASE_URI}0`);
  });

  it('should generate valid token uri metadata when data uris are enabled', async () => {
    const tokenUri = await nounsDescriptor.tokenURI(0, {
      background: 0,
      body: longest.bodies.index,
      accessory: longest.accessories.index,
      head: longest.heads.index,
      glasses: longest.glasses.index,
    });
    const { name, description, image } = JSON.parse(
      Buffer.from(tokenUri.replace('data:application/json;base64,', ''), 'base64').toString(
        'ascii',
      ),
    );
    expect(name).to.equal('Noun 0');
    expect(description).to.equal('Noun 0 is a member of the Nouns DAO');
    expect(image).to.not.be.undefined;
  });

  // Unskip this test to validate the encoding of all parts. It ensures that no parts revert when building the token URI.
  // This test also outputs a parts.html file, which can be visually inspected.
  // Note that this test takes a long time to run. You must increase the mocha timeout to a large number.
  it.skip('should generate valid token uri metadata for all supported parts when data uris are enabled', async () => {
    console.log('Running... this may take a little while...');

    const { bgcolors, images } = ImageData;
    const { bodies, accessories, heads, glasses } = images;
    const max = Math.max(bodies.length, accessories.length, heads.length, glasses.length);
    for (let i = 0; i < max; i++) {
      const tokenUri = await nounsDescriptor.tokenURI(i, {
        background: Math.min(i, bgcolors.length - 1),
        body: Math.min(i, bodies.length - 1),
        accessory: Math.min(i, accessories.length - 1),
        head: Math.min(i, heads.length - 1),
        glasses: Math.min(i, glasses.length - 1),
      });
      const { name, description, image } = JSON.parse(
        Buffer.from(tokenUri.replace('data:application/json;base64,', ''), 'base64').toString(
          'ascii',
        ),
      );
      expect(name).to.equal(`Noun ${i}`);
      expect(description).to.equal(`Noun ${i} is a member of the Nouns DAO`);
      expect(image).to.not.be.undefined;

      appendFileSync(
        'parts.html',
        Buffer.from(image.split(';base64,').pop(), 'base64').toString('ascii'),
      );

      if (i && i % Math.round(max / 10) === 0) {
        console.log(`${Math.round((i / max) * 100)}% complete`);
      }
    }
  });
});