# 10. [Playwright] feat(webServer): support name option for custom web server log prefixes

pengooseDev·어제
0

PR
Issue

1. Issue

현재 Playwright에서 여러개의 웹서버를 띄울 때, 각 서버 로그의 Prefix가 [WebServer]로 고정되어있다.
각 서버별 로그 파악이 용이하도록 defineConfig 함수에 커스텀 prefix 기능요청이 들어왔다.


2. Context 파악


export class WebServerPlugin implements TestRunnerPlugin {
  // ...codes
  private async _startProcess(): Promise<void> {
    // ...codes
    launchedProcess.stderr!.on('data', data => {
      if (debugWebServer.enabled || (this._options.stderr === 'pipe' || !this._options.stderr))
        this._reporter!.onStdErr?.(prefixOutputLines(data.toString())); // ⛳️
    });
    launchedProcess.stdout!.on('data', data => {
      if (debugWebServer.enabled || this._options.stdout === 'pipe')
        this._reporter!.onStdOut?.(prefixOutputLines(data.toString())); // ⛳️
    });
  }

function prefixOutputLines(output: string): string {
  const lastIsNewLine = output[output.length - 1] === '\n';
  let lines = output.split('\n');
  if (lastIsNewLine)
    lines.pop();
  lines = lines.map(line => colors.dim('[WebServer] ') + line); // ⛳️ 1. 호출하면 WebServer Prefix가 하드코딩 되어있음.
  if (lastIsNewLine)
    lines.push('');
  return lines.join('\n');
}

WebServerPlugin 객체의 this._option에 optional로 name 프로퍼티를 추가해준 뒤, defaultValue를 기존 WebServer로 설정한채 상위에서 name을 매개변수로 주입해주면 쉽게 구현이 가능하다.


3. 회귀 테스트

기존 테스트코드 컨벤션에 맞게 테스트를 우선 추가해준다.

test.describe('name option', () => {
  test('should use custom prefix', async ({ runInlineTest }, { workerIndex }) => {
    const port = workerIndex * 2 + 10500;
    const name1 = 'CustomName1';
    const name2 = 'CustomName2';
    const defaultPrefix = 'WebServer';
    const result = await runInlineTest({
      'test.spec.ts': `
      import { test, expect } from '@playwright/test';
      test('pass', async ({}) => {});
    `,
      'playwright.config.ts': `
      module.exports = {
        webServer: [
          {
            command: 'node ${JSON.stringify(SIMPLE_SERVER_PATH)} ${port}',
            port: ${port},
            name: '${name1}',
          },
          {
            command: 'node ${JSON.stringify(SIMPLE_SERVER_PATH)} ${port + 1}',
            port: ${port + 1},
            name: '${name2}',
          }
        ],
      };
    `,
    }, undefined);
    expect(result.exitCode).toBe(0);
    expect(result.output).toContain(`[${name1}]`);
    expect(result.output).toContain(`[${name2}]`);
    expect(result.output).not.toContain(`[${defaultPrefix}]`);
  });

  test('should use default prefix when name option is not set', async ({ runInlineTest }, { workerIndex }) => {
    const port = workerIndex * 2 + 10500;
    const defaultPrefix = 'WebServer';
    const result = await runInlineTest({
      'test.spec.ts': `
      import { test, expect } from '@playwright/test';
      test('pass', async ({}) => {});
    `,
      'playwright.config.ts': `
      module.exports = {
        webServer: {
          command: 'node ${JSON.stringify(SIMPLE_SERVER_PATH)} ${port}',
          port: ${port},
        },
      };
    `,
    }, undefined);
    expect(result.exitCode).toBe(0);
    expect(result.output).toContain(`[${defaultPrefix}]`);
  });
});

4. 해결

export type WebServerPluginOptions = {
  // ...props
  name?: string;
};

필드 추가하고

// ⛳️ 1. DefaultValue는 기존 Prefix(WebServer) 사용
function prefixOutputLines(output: string, prefixName: string = 'WebServer'): string {
  const lastIsNewLine = output[output.length - 1] === '\n';
  let lines = output.split('\n');
  if (lastIsNewLine)
    lines.pop();
  lines = lines.map(line => colors.dim(`[${prefixName}] `) + line); // ⛳️
  if (lastIsNewLine)
    lines.push('');
  return lines.join('\n');
}

동적 할당하고

launchedProcess.stderr!.on('data', data => {
  if (debugWebServer.enabled || (this._options.stderr === 'pipe' || !this._options.stderr))
    this._reporter!.onStdErr?.(prefixOutputLines(data.toString(), this._options.name));
});
launchedProcess.stdout!.on('data', data => {
  if (debugWebServer.enabled || this._options.stdout === 'pipe')
    this._reporter!.onStdOut?.(prefixOutputLines(data.toString(), this._options.name));
});

주입

이후 문서 작성 및 빌드로 타입 생성해주고 완료


5. Merged

0개의 댓글

관련 채용 정보