<commit_before>#!/usr/bin/env node

/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* eslint-disable no-console */

import fs from 'fs';
import os from 'os';
import path from 'path';
import program from 'commander';
import { runDriver, runServer, printApiJson, launchBrowserServer, installBrowsers } from './driver';
import { showTraceViewer } from '../server/trace/viewer/traceViewer';
import * as playwright from '../..';
import { BrowserContext } from '../client/browserContext';
import { Browser } from '../client/browser';
import { Page } from '../client/page';
import { BrowserType } from '../client/browserType';
import { BrowserContextOptions, LaunchOptions } from '../client/types';
import { spawn } from 'child_process';
import { allBrowserNames, BrowserName, Registry } from '../utils/registry';
import * as utils from '../utils/utils';

const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');


type BrowserChannel = 'chrome-beta'|'chrome'|'msedge';
const allBrowserChannels: Set<BrowserChannel> = new Set(['chrome-beta', 'chrome', 'msedge']);
const packageJSON = require('../../package.json');

const ChannelName = {
  'chrome-beta': 'Google Chrome Beta',
  'chrome': 'Google Chrome',
  'msedge': 'Microsoft Edge',
};

const InstallationScriptName = {
  'chrome-beta': {
    'linux': 'reinstall_chrome_beta_linux.sh',
    'darwin': 'reinstall_chrome_beta_mac.sh',
    'win32': 'reinstall_chrome_beta_win.ps1',
  },
  'chrome': {
    'linux': 'reinstall_chrome_stable_linux.sh',
    'darwin': 'reinstall_chrome_stable_mac.sh',
    'win32': 'reinstall_chrome_stable_win.ps1',
  },
  'msedge': {
    'darwin': 'reinstall_msedge_stable_mac.sh',
    'win32': 'reinstall_msedge_stable_win.ps1',
  },
};

program
    .version('Version ' + packageJSON.version)
    .name(process.env.PW_CLI_NAME || 'npx playwright');

commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --browser', [])
    .action(function(url, command) {
      open(command, url, language()).catch(logErrorAndExit);
    })
    .on('--help', function() {
      console.log('');
      console.log('Examples:');
      console.log('');
      console.log('  $ open');
      console.log('  $ open -b webkit https://example.com');
    });

commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions',
    [
      ['-o, --output <file name>', 'saves the generated script to a file'],
      ['--target <language>', `language to generate, one of javascript, test, python, python-async, csharp`, language()],
    ]).action(function(url, command) {
  codegen(command, url, command.target, command.output).catch(logErrorAndExit);
}).on('--help', function() {
  console.log('');
  console.log('Examples:');
  console.log('');
  console.log('  $ codegen');
  console.log('  $ codegen --target=python');
  console.log('  $ codegen -b webkit https://example.com');
});

program
    .command('debug <app> [args...]')
    .description('run command in debug mode: disable timeout, open inspector')
    .action(function(app, args) {
      spawn(app, args, {
        env: { ...process.env, PWDEBUG: '1' },
        stdio: 'inherit'
      });
    }).on('--help', function() {
      console.log('');
      console.log('Examples:');
      console.log('');
      console.log('  $ debug node test.js');
      console.log('  $ debug npm run test');
    });

program
    .command('install [browserType...]')
    .description('ensure browsers necessary for this version of Playwright are installed')
    .action(async function(args) {
      try {
        // Install default browsers when invoked without arguments.
        if (!args.length) {
          await installBrowsers();
          return;
        }
        const browserNames: Set<BrowserName> = new Set(args.filter((browser: any) => allBrowserNames.has(browser)));
        const browserChannels: Set<BrowserChannel> = new Set(args.filter((browser: any) => allBrowserChannels.has(browser)));
        const faultyArguments: string[] = args.filter((browser: any) => !browserNames.has(browser) && !browserChannels.has(browser));
        if (faultyArguments.length) {
          console.log(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${[...allBrowserNames, ...allBrowserChannels].map(name => `'${name}'`).join(', ')}`);
          process.exit(1);
        }
        if (browserNames.has('chromium') || browserChannels.has('chrome-beta') || browserChannels.has('chrome') || browserChannels.has('msedge'))
          browserNames.add('ffmpeg');
        if (browserNames.size)
          await installBrowsers([...browserNames]);
        for (const browserChannel of browserChannels)
          await installBrowserChannel(browserChannel);
      } catch (e) {
        console.log(`Failed to install browsers\n${e}`);
        process.exit(1);
      }
    }).on('--help', function() {
      console.log(``);
      console.log(`Examples:`);
      console.log(`  - $ install`);
      console.log(`    Install default browsers.`);
      console.log(``);
      console.log(`  - $ install chrome firefox`);
      console.log(`    Install custom browsers, supports ${[...allBrowserNames, ...allBrowserChannels].map(name => `'${name}'`).join(', ')}.`);
    });

async function installBrowserChannel(channel: BrowserChannel) {
  const platform = os.platform();
  const scriptName: (string|undefined) = (InstallationScriptName[channel] as any)[platform];
  if (!scriptName)
    throw new Error(`Cannot install ${ChannelName[channel]} on ${platform}`);

  const scriptArgs = [];
  if (channel === 'msedge') {
    const products = JSON.parse(await utils.fetchData('https://edgeupdates.microsoft.com/api/products'));
    const stable = products.find((product: any) => product.Product === 'Stable');
    if (platform === 'win32') {
      const arch = os.arch() === 'x64' ? 'x64' : 'x86';
      const release = stable.Releases.find((release: any) => release.Platform === 'Windows' && release.Architecture === arch);
      const artifact = release.Artifacts.find((artifact: any) => artifact.ArtifactName === 'msi');
      scriptArgs.push(artifact.Location /* url */);
    } else if (platform === 'darwin') {
      const release = stable.Releases.find((release: any) => release.Platform === 'MacOS' && release.Architecture === 'universal');
      const artifact = release.Artifacts.find((artifact: any) => artifact.ArtifactName === 'pkg');
      scriptArgs.push(artifact.Location /* url */);
    } else {
      throw new Error(`Cannot install ${ChannelName[channel]} on ${platform}`);
    }<commit_msg>fix(cli): do not suggest internal tools in `install` command (#7437)<commit_after>#!/usr/bin/env node

/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* eslint-disable no-console */

import fs from 'fs';
import os from 'os';
import path from 'path';
import program from 'commander';
import { runDriver, runServer, printApiJson, launchBrowserServer, installBrowsers } from './driver';
import { showTraceViewer } from '../server/trace/viewer/traceViewer';
import * as playwright from '../..';
import { BrowserContext } from '../client/browserContext';
import { Browser } from '../client/browser';
import { Page } from '../client/page';
import { BrowserType } from '../client/browserType';
import { BrowserContextOptions, LaunchOptions } from '../client/types';
import { spawn } from 'child_process';
import { allBrowserNames, BrowserName, Registry } from '../utils/registry';
import * as utils from '../utils/utils';

const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');


type BrowserChannel = 'chrome-beta'|'chrome'|'msedge';
const allBrowserChannels: Set<BrowserChannel> = new Set(['chrome-beta', 'chrome', 'msedge']);
const suggestedBrowsersToInstall = ['chromium', 'webkit', 'firefox', ...allBrowserChannels].map(name => `'${name}'`).join(', ');
const packageJSON = require('../../package.json');

const ChannelName = {
  'chrome-beta': 'Google Chrome Beta',
  'chrome': 'Google Chrome',
  'msedge': 'Microsoft Edge',
};

const InstallationScriptName = {
  'chrome-beta': {
    'linux': 'reinstall_chrome_beta_linux.sh',
    'darwin': 'reinstall_chrome_beta_mac.sh',
    'win32': 'reinstall_chrome_beta_win.ps1',
  },
  'chrome': {
    'linux': 'reinstall_chrome_stable_linux.sh',
    'darwin': 'reinstall_chrome_stable_mac.sh',
    'win32': 'reinstall_chrome_stable_win.ps1',
  },
  'msedge': {
    'darwin': 'reinstall_msedge_stable_mac.sh',
    'win32': 'reinstall_msedge_stable_win.ps1',
  },
};

program
    .version('Version ' + packageJSON.version)
    .name(process.env.PW_CLI_NAME || 'npx playwright');

commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --browser', [])
    .action(function(url, command) {
      open(command, url, language()).catch(logErrorAndExit);
    })
    .on('--help', function() {
      console.log('');
      console.log('Examples:');
      console.log('');
      console.log('  $ open');
      console.log('  $ open -b webkit https://example.com');
    });

commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions',
    [
      ['-o, --output <file name>', 'saves the generated script to a file'],
      ['--target <language>', `language to generate, one of javascript, test, python, python-async, csharp`, language()],
    ]).action(function(url, command) {
  codegen(command, url, command.target, command.output).catch(logErrorAndExit);
}).on('--help', function() {
  console.log('');
  console.log('Examples:');
  console.log('');
  console.log('  $ codegen');
  console.log('  $ codegen --target=python');
  console.log('  $ codegen -b webkit https://example.com');
});

program
    .command('debug <app> [args...]')
    .description('run command in debug mode: disable timeout, open inspector')
    .action(function(app, args) {
      spawn(app, args, {
        env: { ...process.env, PWDEBUG: '1' },
        stdio: 'inherit'
      });
    }).on('--help', function() {
      console.log('');
      console.log('Examples:');
      console.log('');
      console.log('  $ debug node test.js');
      console.log('  $ debug npm run test');
    });

program
    .command('install [browserType...]')
    .description('ensure browsers necessary for this version of Playwright are installed')
    .action(async function(args) {
      try {
        // Install default browsers when invoked without arguments.
        if (!args.length) {
          await installBrowsers();
          return;
        }
        const browserNames: Set<BrowserName> = new Set(args.filter((browser: any) => allBrowserNames.has(browser)));
        const browserChannels: Set<BrowserChannel> = new Set(args.filter((browser: any) => allBrowserChannels.has(browser)));
        const faultyArguments: string[] = args.filter((browser: any) => !browserNames.has(browser) && !browserChannels.has(browser));
        if (faultyArguments.length) {
          console.log(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall}`);
          process.exit(1);
        }
        if (browserNames.has('chromium') || browserChannels.has('chrome-beta') || browserChannels.has('chrome') || browserChannels.has('msedge'))
          browserNames.add('ffmpeg');
        if (browserNames.size)
          await installBrowsers([...browserNames]);
        for (const browserChannel of browserChannels)
          await installBrowserChannel(browserChannel);
      } catch (e) {
        console.log(`Failed to install browsers\n${e}`);
        process.exit(1);
      }
    }).on('--help', function() {
      console.log(``);
      console.log(`Examples:`);
      console.log(`  - $ install`);
      console.log(`    Install default browsers.`);
      console.log(``);
      console.log(`  - $ install chrome firefox`);
      console.log(`    Install custom browsers, supports ${suggestedBrowsersToInstall}.`);
    });

async function installBrowserChannel(channel: BrowserChannel) {
  const platform = os.platform();
  const scriptName: (string|undefined) = (InstallationScriptName[channel] as any)[platform];
  if (!scriptName)
    throw new Error(`Cannot install ${ChannelName[channel]} on ${platform}`);

  const scriptArgs = [];
  if (channel === 'msedge') {
    const products = JSON.parse(await utils.fetchData('https://edgeupdates.microsoft.com/api/products'));
    const stable = products.find((product: any) => product.Product === 'Stable');
    if (platform === 'win32') {
      const arch = os.arch() === 'x64' ? 'x64' : 'x86';
      const release = stable.Releases.find((release: any) => release.Platform === 'Windows' && release.Architecture === arch);
      const artifact = release.Artifacts.find((artifact: any) => artifact.ArtifactName === 'msi');
      scriptArgs.push(artifact.Location /* url */);
    } else if (platform === 'darwin') {
      const release = stable.Releases.find((release: any) => release.Platform === 'MacOS' && release.Architecture === 'universal');
      const artifact = release.Artifacts.find((artifact: any) => artifact.ArtifactName === 'pkg');
      scriptArgs.push(artifact.Location /* url */);
    } else {
      throw new Error(`Cannot install ${ChannelName[channel]} on ${platform}`);
    }
{'fraction_non_alphanumeric': 0.16840495063273536, 'fraction_numerical': 0.00361563064942289, 'mean_word_length': 3.656199417287148, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 36, 'https://': 6, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2431800', 'n_tokens_mistral': 4265, 'n_tokens_neox': 4176, 'n_words': 1070}