Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  utils.ts   Sprache: unbekannt

 
/**
 * @license
 * Copyright 2022 Google Inc.
 * SPDX-License-Identifier: Apache-2.0
 */

import fs from 'fs';
import path from 'path';

import type {
  MochaTestResult,
  TestExpectation,
  MochaResults,
  TestResult,
} from './types.js';

export function extendProcessEnv(envs: object[]): NodeJS.ProcessEnv {
  const env = envs.reduce(
    (acc: object, item: object) => {
      Object.assign(acc, item);
      return acc;
    },
    {
      ...process.env,
    },
  );

  if (process.env['CI']) {
    const puppeteerEnv = Object.entries(env).reduce(
      (acc, [key, value]) => {
        if (key.startsWith('PUPPETEER_')) {
          acc[key] = value;
        }

        return acc;
      },
      {} as Record<string, unknown>,
    );

    console.log(
      'PUPPETEER env:\n',
      JSON.stringify(puppeteerEnv, null, 2),
      '\n',
    );
  }

  return env as NodeJS.ProcessEnv;
}

export function getFilename(file: string): string {
  return path.basename(file).replace(path.extname(file), '');
}

export function readJSON(path: string): unknown {
  return JSON.parse(fs.readFileSync(path, 'utf-8'));
}

export function writeJSON(path: string, json: unknown): unknown {
  return fs.writeFileSync(path, JSON.stringify(json, null, 2));
}

export function filterByPlatform<T extends {platforms: NodeJS.Platform[]}>(
  items: T[],
  platform: NodeJS.Platform,
): T[] {
  return items.filter(item => {
    return item.platforms.includes(platform);
  });
}

export function prettyPrintJSON(json: unknown): void {
  console.log(JSON.stringify(json, null, 2));
}

export function getSuggestionsForAction(
  recommendations: RecommendedExpectation[],
  action: RecommendedExpectation['action'],
): RecommendedExpectation[] {
  return recommendations.filter(item => {
    return item.action === action;
  });
}

export function printSuggestions(
  recommendations: RecommendedExpectation[],
  message: string,
  printBasedOn = false,
): void {
  if (recommendations.length) {
    console.log(message);
    prettyPrintJSON(
      recommendations.map(item => {
        return item.expectation;
      }),
    );
    if (printBasedOn) {
      console.log(
        'The recommendations are based on the following applied expectations:',
      );
      prettyPrintJSON(
        recommendations.map(item => {
          return item.basedOn;
        }),
      );
    }
  }
}

export function filterByParameters(
  expectations: TestExpectation[],
  parameters: string[],
): TestExpectation[] {
  const querySet = new Set(parameters);
  return expectations.filter(ex => {
    return ex.parameters.every(param => {
      return querySet.has(param);
    });
  });
}

/**
 * The last expectation that matches an empty string as all tests pattern
 * or the name of the file or the whole name of the test the filter wins.
 */
export function findEffectiveExpectationForTest(
  expectations: TestExpectation[],
  result: MochaTestResult,
): TestExpectation | undefined {
  return expectations.find(expectation => {
    return testIdMatchesExpectationPattern(result, expectation.testIdPattern);
  });
}

export interface RecommendedExpectation {
  expectation: TestExpectation;
  action: 'remove' | 'add' | 'update';
  basedOn?: TestExpectation;
}

export function isWildCardPattern(testIdPattern: string): boolean {
  return testIdPattern.includes('*');
}

export function getExpectationUpdates(
  results: MochaResults,
  expectations: TestExpectation[],
  context: {
    platforms: NodeJS.Platform[];
    parameters: string[];
  },
): RecommendedExpectation[] {
  const output = new Map<string, RecommendedExpectation>();

  const passesByKey = results.passes.reduce((acc, pass) => {
    acc.add(getTestId(pass.file, pass.fullTitle));
    return acc;
  }, new Set());

  for (const pass of results.passes) {
    const expectationEntry = findEffectiveExpectationForTest(
      expectations,
      pass,
    );
    if (expectationEntry && !expectationEntry.expectations.includes('PASS')) {
      if (isWildCardPattern(expectationEntry.testIdPattern)) {
        addEntry({
          expectation: {
            testIdPattern: getTestId(pass.file, pass.fullTitle),
            platforms: context.platforms,
            parameters: context.parameters,
            expectations: ['PASS'],
          },
          action: 'add',
          basedOn: expectationEntry,
        });
      } else {
        addEntry({
          expectation: expectationEntry,
          action: 'remove',
          basedOn: expectationEntry,
        });
      }
    }
  }

  for (const failure of results.failures) {
    // If an error occurs during a hook
    // the error not have a file associated with it
    if (!failure.file) {
      console.error('Hook failed:', failure.err);
      addEntry({
        expectation: {
          testIdPattern: failure.fullTitle,
          platforms: context.platforms,
          parameters: context.parameters,
          expectations: [],
        },
        action: 'add',
      });
      continue;
    }

    if (passesByKey.has(getTestId(failure.file, failure.fullTitle))) {
      continue;
    }

    const expectationEntry = findEffectiveExpectationForTest(
      expectations,
      failure,
    );
    if (expectationEntry && !expectationEntry.expectations.includes('SKIP')) {
      if (
        !expectationEntry.expectations.includes(
          getTestResultForFailure(failure),
        )
      ) {
        // If the effective explanation is a wildcard, we recommend adding a new
        // expectation instead of updating the wildcard that might affect multiple
        // tests.
        if (isWildCardPattern(expectationEntry.testIdPattern)) {
          addEntry({
            expectation: {
              testIdPattern: getTestId(failure.file, failure.fullTitle),
              platforms: context.platforms,
              parameters: context.parameters,
              expectations: [getTestResultForFailure(failure)],
            },
            action: 'add',
            basedOn: expectationEntry,
          });
        } else {
          addEntry({
            expectation: {
              ...expectationEntry,
              expectations: [
                ...expectationEntry.expectations,
                getTestResultForFailure(failure),
              ],
            },
            action: 'update',
            basedOn: expectationEntry,
          });
        }
      }
    } else if (!expectationEntry) {
      addEntry({
        expectation: {
          testIdPattern: getTestId(failure.file, failure.fullTitle),
          platforms: context.platforms,
          parameters: context.parameters,
          expectations: [getTestResultForFailure(failure)],
        },
        action: 'add',
      });
    }
  }

  function addEntry(value: RecommendedExpectation) {
    const key = JSON.stringify(value);
    if (!output.has(key)) {
      output.set(key, value);
    }
  }

  return [...output.values()];
}

export function getTestResultForFailure(
  test: Pick<MochaTestResult, 'err'>,
): TestResult {
  return test.err?.code === 'ERR_MOCHA_TIMEOUT' ? 'TIMEOUT' : 'FAIL';
}

export function getTestId(file: string, fullTitle?: string): string {
  return fullTitle
    ? `[${getFilename(file)}] ${fullTitle}`
    : `[${getFilename(file)}]`;
}

export function testIdMatchesExpectationPattern(
  test: MochaTestResult | Pick<Mocha.Test, 'title' | 'file' | 'fullTitle'>,
  pattern: string,
): boolean {
  const patternRegExString = pattern
    // Replace `*` with non special character
    .replace(/\*/g, '--STAR--')
    // Escape special characters https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
    .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
    // Replace placeholder with greedy match
    .replace(/--STAR--/g, '(.*)?');
  // Match beginning and end explicitly
  const patternRegEx = new RegExp(`^${patternRegExString}$`);
  const fullTitle =
    typeof test.fullTitle === 'string' ? test.fullTitle : test.fullTitle();

  return patternRegEx.test(getTestId(test.file ?? '', fullTitle));
}

[ Dauer der Verarbeitung: 0.31 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge