본문 바로가기
자동화(Automation)/Playwright

Playwright_Tab

by Testengineer 2025. 12. 1.
반응형

사실 웹에서 자동화 처리를 하게 되면 필연적으로 사용하게 되는 부분이 탭 이용방법이라고 생각합니다. 새 탭으로 열린 화면을 검증하거나, 혹은 여러 탭에서 특정탭에서 특정행동을 한다거나, 탭을 닫는 행동 등 굉장히 많은 사용자가 원하는 방향이 다양하게 있을 것 같습니다.

그래서 이번에는 Playwright에서 탭을 이용하는 방법에 관해서 포스팅해보고자 합니다.

모든 예시문은 JavaScript를 사용해서 작성되었습니다.

 

먼저, 한 개의 새탭이 열린 경우를 가정하고 새 탭이 열리고 그 페이지의 URL을 검증하고 탭을 닫는 코드에 관해 작성해 보겠습니다.

const { test, expect } = require('@playwright/test');

test('새 탭 열기 및 검증', async ({ page, context }) => {
  await page.goto('https://example.com');
  
  // 새 탭이 열릴 것을 대기하는 Promise 생성
  const [newPage] = await Promise.all([
    context.waitForEvent('page'), // 새 페이지(탭) 대기
    page.click('text=새창으로 열기') // 버튼 클릭
  ]);
  
  // 새 탭이 로드될 때까지 대기
  await newPage.waitForLoadState();
  
  // 새 탭의 URL 검증
  await expect(newPage).toHaveURL('https://example.com/new-page');
  console.log('새 탭 URL:', newPage.url());
  
  // 새 탭 닫기
  await newPage.close();
  
  // 원래 탭으로 자동으로 돌아옴
  console.log('원래 탭 URL:', page.url());
  
  // 원래 탭에서 작업 계속
  await expect(page).toHaveURL('https://example.com');
});

새 페이지인 새 탭이 열릴 경우 const [newPage]에 값을 넣어주면 됩니다.  Promise.all을 통해 새 탭이 열릴 때 대기했다가 위의 예시인 경우는 새 탭의 URL을 검증하고, 닫고 원래 탭으로 자동으로 돌아오는지 확인하는 코드입니다.

 

두 번째는 열린 모든 탭을 확인하는 경우 모든 탭의 정보를 가져와서 처리하는 방식에 대해 작성해 보겠습니다.

const { test, expect } = require('@playwright/test');

test('열린 모든 탭 확인', async ({ page, context }) => {
  await page.goto('https://example.com');
  
  // 여러 새 탭 열기
  const [newPage1] = await Promise.all([
    context.waitForEvent('page'),
    page.click('text=링크1')
  ]);
  
  const [newPage2] = await Promise.all([
    context.waitForEvent('page'),
    page.click('text=링크2')
  ]);
  
  // 현재 열린 모든 페이지(탭) 가져오기
  const pages = context.pages();
  console.log('열린 탭 개수:', pages.length); // 3개 (원래 탭 + 새 탭 2개)
  
  // 각 탭의 URL 출력
  for (const p of pages) {
    console.log('탭 URL:', p.url());
  }
  
  // 새 탭들 모두 닫기
  await newPage1.close();
  await newPage2.close();
  
  // 다시 확인
  console.log('남은 탭 개수:', context.pages().length); // 1개
});

위의 코드는 이미 열린 탭 1개와 추가로 newPage1, newPage2의 새 탭이 열렸고 context.pages()를 이용해 현재 모든 열린 페이지 개수를 가져와서 열린 탭의 개수와 각 탭의 URL을 출력하는 예시입니다. 

이 방법을 사용하면 for 반복문을 이용해서 열린 모든 탭의 URL을 출력하는 방법을 사용할 수 있습니다. 

 

세 번째는 여러 새 탭을 순차적으로 처리하는 시나리오일 때 사용되는 코드입니다.

async function openVerifyAndCloseTab(context, clickAction, expectedURL) {
  const [newPage] = await Promise.all([
    context.waitForEvent('page'),
    clickAction()
  ]);
  
  await newPage.waitForLoadState();
  await expect(newPage).toHaveURL(expectedURL);
  
  const url = newPage.url();
  await newPage.close();
  
  return url;
}

// 여러 새 탭을 순차적으로 처리
async function handleMultipleTabs(context, tabConfigs) {
  const results = [];
  
  for (const config of tabConfigs) {
    const url = await openVerifyAndCloseTab(
      context,
      config.clickAction,
      config.expectedURL
    );
    
    results.push({
      name: config.name,
      url: url,
      success: true
    });
  }
  
  return results;
}

위에서는 handleMultipleTabs 함수를 따로 분리해서 아래에 있는 test문에서 이용하는 방식을 사용한 것이라고 봐주시면 됩니다.

함수를 따로 작성하면 재사용성에 좋기 때문에, 제일 처음 설명했었던 새 탭을 열고 URL을 검증하고 닫는 방식도 openVerifyAndCloseTab 함수로 작성되었습니다. 이 방식을 이용해서 여러 새 탭을 순차적으로 처리할 수 있습니다. 

handleMultipleTabs에서는 새 탭이 열리면 이름을 확인하고 버튼을 클릭해서 새 탭이 기대한 URL과 일치하면 탭을 닫아주는 방식을 처리하고 results에 success true값을 전달시켜 줍니다. 

그렇게 아래의 test문인 '여러 링크 일괄 처리' 예시처럼 보통 웹 사이트 푸터에 위치한 이용약관, 개인정보 처리방침, FAQ 같은 새 창들을 확인할 수 있게 됩니다.

test('여러 링크 일괄 처리', async ({ page, context }) => {
  await page.goto('https://example.com/signup');
  
  // 여러 탭을 순차적으로 처리
  const results = await handleMultipleTabs(context, [
    {
      name: '이용약관',
      clickAction: () => page.click('text=이용약관'),
      expectedURL: /terms/
    },
    {
      name: '개인정보처리방침',
      clickAction: () => page.click('text=개인정보처리방침'),
      expectedURL: /privacy/
    },
    {
      name: 'FAQ',
      clickAction: () => page.click('text=자주 묻는 질문'),
      expectedURL: /faq/
    }
  ]);

위에 세 가지 방식을 이용하면 대부분의 탭을 이용한 처리에서 니즈에 맞게 바꿔 사용가능할 것입니다. 다만 탭 말고도, 팝업창이나 프레임워크 같이 새 창의 형태 역시 필요한 부분인 만큼 이 부분에 관해서는 다음 포스팅에서 다뤄보려고 합니다. 

 

 

반응형