Skip to content

Commit

Permalink
Merge branch 'main' into column-sort-arrows
Browse files Browse the repository at this point in the history
  • Loading branch information
JakeWags authored Feb 20, 2024
2 parents 2e5383e + 35b37c1 commit 810e410
Show file tree
Hide file tree
Showing 17 changed files with 1,017 additions and 44,694 deletions.
64 changes: 64 additions & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Playwright Tests

on:
pull_request:
branches:
- main

jobs:
test:
name: 🧪 ${{ matrix.project }} E2E Tests
runs-on: ${{ matrix.os }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- project: chromium
os: ubuntu-latest
cache_dir: ~/.cache/ms-playwright

- project: firefox
os: ubuntu-latest
cache_dir: ~/.cache/ms-playwright

- project: webkit
os: macos-14
cache_dir: ~/Library/Caches/ms-playwright
steps:
- uses: actions/checkout@v3

- uses: actions/setup-node@v3
with:
node-version: lts/*
cache: "yarn"

- name: Install dependencies
run: yarn install --immutable

- name: Write out playwright version
run: yarn --silent playwright --version > .playwright-version

- name: ⚡️ Cache playwright binaries
uses: actions/cache@v3
id: playwright-cache
with:
path: ${{ matrix.cache_dir }}
key: ${{ runner.os }}-${{ matrix.project }}-pw-${{ hashFiles('**/.playwright-version') }}

- name: Install Playwright Browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn playwright install --with-deps ${{ matrix.project }}

- name: Run yarn build
run: yarn build

- name: Run Playwright tests
run: yarn test --project=${{ matrix.project }}

- name: Upload test results
if: failure()
uses: actions/upload-artifact@v3
with:
name: playwright-report
path: playwright-report
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,10 @@ psd
thumb
sketch

# playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

# End of https://www.toptal.com/developers/gitignore/api/react,node,joed
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,14 @@ To deploy UpSet 2.0 locally it is necessary to install the Multinet infrastructu

To run UpSet 2.0 locally, first, complete the [Local Installation](#local-installation) steps. Then, use `yarn dev` to run UpSet 2.0 on port 3000.
A browser window for `localhost:3000` will open during the launch process.

## End To End (e2e) Testing

To run the playwright end to end tests, use the command:
`yarn test`

To open the test in a UI view to track steps, append `--ui`.

This will launch a local server if there is not one already running on port 3000.

To add a test, add a `.spec.ts` file to `e2e-tests`. For information on how to use playwright, please see the [playwright documentation](https://playwright.dev/docs/writing-tests).
125 changes: 125 additions & 0 deletions e2e-tests/alttext.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/* eslint-disable testing-library/prefer-screen-queries */
import { test, expect } from '@playwright/test';
import mockData from '../playwright/mock-data/simpsons/simpsons_data.json';
import mockAnnotations from '../playwright/mock-data/simpsons/simpsons_annotations.json';
import mockAltText from '../playwright/mock-data/simpsons/simpsons_alttxt.json';

test.beforeEach(async ({ page }) => {
await page.route('*/**/api/**', async (route) => {
const url = route.request().url();
let json;

if (url) {
if (url.includes('workspaces/Upset%20Examples/tables/simpsons/rows/?limit=9007199254740991')) {
json = mockData;
await route.fulfill({ json });
} else if (url.includes('workspaces/Upset%20Examples/tables/simpsons/annotations/')) {
json = mockAnnotations;
await route.fulfill({ json });
} else if (url.includes('alttxt')) {
json = mockAltText;
await route.fulfill({ json });
} else if (url.includes('workspaces/Upset%20Examples/sessions/table/193/state/')) {
await route.fulfill({ status: 200 });
} else {
await route.continue();
}
} else {
await route.abort();
}
});
});

test('Alt Text', async ({ page }) => {
await page.goto('http://localhost:3000/?workspace=Upset+Examples&table=simpsons&sessionId=193');

const altTextSidebarButton = await page.getByLabel('Open alt text sidebar');
await expect(altTextSidebarButton).toBeVisible();
await altTextSidebarButton.click();

const altTextSidebar = await page.getByLabel('Alt Text Sidebar', { exact: true });
await expect(altTextSidebar).toBeVisible();

const altTextHeading = await page.getByRole('heading', { name: 'Alt Text' });
await expect(altTextHeading).toBeVisible();

/// /////////////////
// Plot Information
/// /////////////////
const plotInformation = await page.getByRole('button', { name: 'Plot Information' });
await expect(plotInformation).toBeVisible();
await plotInformation.click();

const editPlotInformationButton = await page.getByLabel('Toggle editable descriptions');
await expect(editPlotInformationButton).toBeVisible();
await editPlotInformationButton.click();

const datasetDescriptionInput = await page.getByPlaceholder('eg: movie genres and ratings');
await expect(datasetDescriptionInput).toBeVisible();
await expect(datasetDescriptionInput).toBeEditable();
await datasetDescriptionInput.click();
await datasetDescriptionInput.fill('Test dataset description');

const setsInput = await page.getByPlaceholder('eg: movie genres (dataset');
await expect(setsInput).toBeVisible();
await expect(setsInput).toBeEditable();
await setsInput.click();
await setsInput.fill('Test sets value');

const itemsInput = await page.getByPlaceholder('eg: movies (dataset rows)');
await expect(itemsInput).toBeVisible();
await expect(itemsInput).toBeEditable();
await itemsInput.click();
await itemsInput.fill('Test items value');

const plotInformationOutput = await page.getByText('This UpSet plot shows test');
await expect(plotInformationOutput).toBeVisible();
await expect(plotInformationOutput).toHaveText('This UpSet plot shows Test dataset description. The sets are Test sets value. The items are Test items value.');

await page.getByRole('button', { name: 'Save' }).click();
await plotInformation.click();

/// /////////////////
// Alt Text Output
/// /////////////////
const UpSetIntroduction = {
heading: await page.getByRole('heading', { name: 'UpSet Introduction' }),
content: await page.getByText('This is an UpSet plot that'),
};
await expect(UpSetIntroduction.heading).toBeVisible();
await expect(UpSetIntroduction.content).toBeVisible();
await expect(UpSetIntroduction.content).toHaveText('This is an UpSet plot that visualizes set intersection. To learn about UpSet plots, visit https://upset.app.');

const datasetProperties = {
heading: await page.getByRole('heading', { name: 'Dataset Properties' }),
content: await page.getByText('The dataset contains 6 sets'),
};

await expect(datasetProperties.heading).toBeVisible();
await expect(datasetProperties.content).toBeVisible();
await expect(datasetProperties.content).toHaveText('The dataset contains 6 sets, and 44 elements, of which 6 are shown in the plot.');

const setProperties = {
heading: await page.getByRole('heading', { name: 'Set Properties', exact: true }),
content: await page.getByText('The largest set is Male with'),
};
await expect(setProperties.heading).toBeVisible();
await expect(setProperties.content).toBeVisible();
await expect(setProperties.content).toHaveText('The largest set is Male with 18 elements, followed by School with 6, Duff Fan with 6, Evil with 6, Power Plant with 5, and Blue Hair with 3.');

const intersectionProperties = {
heading: await page.getByRole('heading', { name: 'Intersection Properties' }),
content: await page.getByText('The plot is sorted by size.'),
};
await expect(intersectionProperties.heading).toBeVisible();
await expect(intersectionProperties.content).toBeVisible();
await expect(intersectionProperties.content).toHaveText('The plot is sorted by size. There are 12 non-empty intersections, all of which are shown in the plot. The largest 5 intersections are School Male (3), the empty intersection (3), Just Male (3), Duff_Fan Male Power_Plant (3), and Evil Male (2).');

const statisticalInformation = {
heading: await page.getByRole('heading', { name: 'Statistical Information' }),
content: await page.getByText('The average intersection size'),
};
await expect(statisticalInformation.heading).toBeVisible();
await expect(statisticalInformation.content).toBeVisible();
await expect(statisticalInformation.content).toHaveText('The average intersection size is 2, and the median is 2. The 90th percentile is 3, and the 10th percentile is 1. The largest set, Male, is present in 75.0% of all non-empty intersections. The smallest set, Blue Hair, is present in 0.0% of all non-empty intersections.');
});
81 changes: 81 additions & 0 deletions e2e-tests/datatable.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* eslint-disable testing-library/prefer-screen-queries */
import { test, expect } from '@playwright/test';
import mockData from '../playwright/mock-data/simpsons/simpsons_data.json';
import mockAnnotations from '../playwright/mock-data/simpsons/simpsons_annotations.json';
import mockAltText from '../playwright/mock-data/simpsons/simpsons_alttxt.json';

test.beforeEach(async ({ page }) => {
await page.route('*/**/api/**', async (route) => {
const url = route.request().url();
let json;

if (url) {
if (url.includes('workspaces/Upset%20Examples/tables/simpsons/rows/?limit=9007199254740991')) {
json = mockData;
await route.fulfill({ json });
} else if (url.includes('workspaces/Upset%20Examples/tables/simpsons/annotations/')) {
json = mockAnnotations;
await route.fulfill({ json });
} else if (url.includes('alttxt')) {
json = mockAltText;
await route.fulfill({ json });
} else if (url.includes('workspaces/Upset%20Examples/sessions/table/193/state/')) {
await route.fulfill({ status: 200 });
} else {
await route.continue();
}
} else {
await route.abort();
}
});
});

test('Datatable', async ({ page }) => {
await page.goto('http://localhost:3000/?workspace=Upset+Examples&table=simpsons&sessionId=193');

// //////////////////
// Open the datatable
// //////////////////
const page1Promise = page.waitForEvent('popup');
await page.getByRole('button', { name: 'Data Table' }).click();

// //////////////////
// Test downloads
// //////////////////
const page1 = await page1Promise;
const heading1 = await page1.getByRole('heading', { name: 'UpSet Data Table' });
await expect(heading1).toBeVisible();

const downloadPromise = page1.waitForEvent('download');
const downloadButton = await page1.locator('div').filter({ hasText: /^UpSet Data TableDownload$/ }).getByRole('button');
await expect(downloadButton).toBeVisible();
await downloadButton.click();
const download = await downloadPromise;
await expect(download).not.toBeNull();

const heading2 = await page1.getByRole('heading', { name: 'Visible Sets' });
await expect(heading2).toBeVisible();
const download2Promise = page1.waitForEvent('download');
const downloadButton2 = await page1.locator('div').filter({ hasText: /^Visible SetsDownload$/ }).getByRole('button');
await expect(downloadButton2).toBeVisible();
await downloadButton2.click();
const download2 = await download2Promise;
await expect(download2).not.toBeNull();

// there is no download event because there are no hidden sets in this dataset
const heading3 = await page1.getByRole('heading', { name: 'Hidden Sets' });
await expect(heading3).toBeVisible();

const downloadButton3 = await page1.locator('div').filter({ hasText: /^Hidden SetsDownload$/ }).getByRole('button');
await expect(downloadButton3).toBeVisible();

// //////////////////
// Test that the tables exist
// //////////////////
const datatable = await page1.getByText('IntersectionSizeSchool Male3Unincluded3Just Male3Duff_Fan Male Power_Plant3Evil Male2Evil Male Power_Plant2Duff_Fan Male2Just Blue_Hair2Just School1School Evil Male1Rows per page:101–10 of');
await expect(datatable).toBeVisible();
const visibleSets = await page1.getByText('SetSizeSchool6Blue_Hair3Duff_Fan6Evil6Male18Power_Plant5Rows per page:101–6 of');
await expect(visibleSets).toBeVisible();
const hiddenSets = await page1.getByText('No rowsSetSizeRows per page:100–0 of');
await expect(hiddenSets).toBeVisible();
});
Loading

0 comments on commit 810e410

Please sign in to comment.