Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NO-REF: Fixing docker file and playwright tests #547

Merged
merged 10 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
APP_ENV=testing
APP_ENV=development

# API ENDPOINT
API_URL=https://backend.msw
API_URL=https://drb-api-qa.nypl.org/
30 changes: 24 additions & 6 deletions .github/workflows/Playwright.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: Playwright Tests for Digital Research Books

on:
pull_request:
# TODO: Remove https://drb-api-qa.nypl.org from behind the VPC
# on:
# pull_request:

jobs:
tests:
Expand All @@ -15,18 +16,35 @@ jobs:
with:
node-version-file: ".nvmrc"

- name: Install Deps
- name: Install Test Dependencies
run: npm i @cucumber/[email protected] @playwright/[email protected]

- name: Install Playwright
run: npx playwright install --with-deps

- name: Build app
run: NODE_ENV=test npm run build

- name: Start the app
run: npm run dev &
shell: bash

- name: Wait for the app
run: |
RETRIES=6
until curl --output /dev/null --silent --head --fail http://localhost:3000 || [ $((RETRIES--)) -eq 0 ]; do
echo "Waiting for http://localhost:3000"
sleep 5
done
if [ $RETRIES -lt 0 ]; then
echo "Failed to connect to http://localhost:3000"
exit 1
fi
shell: bash

- name: Run your tests
run: npm run playwright

- name: Install Playwright Browser Utils
run: npx playwright install --with-deps

- name: Set the world parameters as an env var
# WORLD_PARAMETERS set here will override anything set in cucumber.json
run: |
Expand Down
45 changes: 0 additions & 45 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,51 +123,6 @@ jobs:
- name: Test
run: npm run test

playwright_test:
name: Playwright Integration Tests
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v1.46.0-jammy
env:
CI: true
steps:
- uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: npm

- name: Cache node modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
# npm cache files are stored in `~/.npm` on Linux/macOS
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-

- name: Install Dependencies
run: npm ci

- name: Build app
run: NODE_ENV=test npm run build

- name: Test
run: npm run playwright

- uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: /playwright-report/
retention-days: 4

docker_build:
# Don't push anything to ECR, just build the docker image to make sure there are no build failures
name: Build Docker Image
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ newrelic_agent.log

# playwright
playwright-report
test-results
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [Prerelease]
- Add submit feedback error handling and new fields
- Fix docker file and playwright tests

## [0.18.5]
- Make NYPL footer sticky
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ ARG NEXT_PUBLIC_ADOBE_ANALYTICS
ARG APP_ENV

# Build the app!
RUN npm run build

ENV PATH /app/node_modules/.bin:$PATH
ENV PORT=3000 \
NODE_ENV=production
Expand All @@ -32,6 +30,8 @@ ENV NEW_RELIC_APP_NAME $NEW_RELIC_APP_NAME
ENV NEXT_PUBLIC_ADOBE_ANALYTICS $NEXT_PUBLIC_ADOBE_ANALYTICS
ENV APP_ENV $APP_ENV

RUN npm run build

# RUNNER, copy all the files and run next
FROM base AS runner
WORKDIR /app
Expand Down
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: "3"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Version is obsolete!

services:
web:
container_name: sfr-bookfinder-front-end
Expand Down
4 changes: 2 additions & 2 deletions mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import {
INVALID_COLLECTION_PATH,
DOWNLOAD_PATH,
FULFILL_PATH,
LIMITED_ACCESS_WORK_PATH,
WORK_PATH,
} from "./mockEnv";

const isAuthenticated = (request) => {
const auth = request.headers.get("authorization");
return auth === "Bearer access-token";
};

const workUrl = new URL(LIMITED_ACCESS_WORK_PATH, API_URL).toString();
const workUrl = new URL(WORK_PATH, API_URL).toString();
const fulfillUrl = new URL(FULFILL_PATH, API_URL).toString();
const downloadUrl = new URL(DOWNLOAD_PATH, API_URL).toString();
const collectionListUrl = new URL(COLLECTION_LIST_PATH, API_URL).toString();
Expand Down
8 changes: 3 additions & 5 deletions mocks/mockEnv.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
export const NYPL_LOGIN_URL = "https://login.nypl.org/auth/login?redirect_uri=";
export const API_URL = "https://backend.msw";
export const FULFILL_PATH = "/fulfill/12345";
export const LIMITED_ACCESS_WORK_PATH =
"/work/12345678-1234-1234-1234-1234567890ab";
export const FULFILL_PATH = "/fulfill/9351827";
export const LIMITED_ACCESS_EDITION_PATH = "/edition/6977884";
export const WORK_PATH = "/work/5950e6df-9d99-42fe-8924-1116166a2acb";
export const DOWNLOAD_PATH = "/test-download-pdf";
export const HOME_PATH = "/";
export const COLLECTION_LIST_PATH = "/collection/list";
export const COLLECTION_PATH =
"/collection/978ea0e0-8ecc-4de2-bfe8-032fea641d8e?page=1";
export const INVALID_COLLECTION_PATH = "/collection/invalid-collection";
27 changes: 12 additions & 15 deletions playwright/integration/auth.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { test, expect } from "../support/test-utils";
import {
API_URL,
FULFILL_PATH,
LIMITED_ACCESS_WORK_PATH,
LIMITED_ACCESS_EDITION_PATH,
NYPL_LOGIN_URL,
} from "~/mocks/mockEnv";
import { server } from "~/mocks/server";
import { LOGIN_TO_READ_TEST_ID } from "~/src/constants/testIds";

test.beforeEach(async ({ context }) => {
await context.clearCookies();
Expand All @@ -14,39 +15,35 @@ test.afterEach(() => server.resetHandlers());
test.afterAll(() => server.close());

test.describe("Cookie authentication", () => {
test("redirects to NYPL log in page with no cookie", async ({
page,
port,
}) => {
await page.goto(`http://localhost:${port}${LIMITED_ACCESS_WORK_PATH}`);
await page.getByRole("link", { name: "title Download PDF" }).click();
test("redirects to NYPL log in page with no cookie", async ({ page }) => {
await page.goto(`${LIMITED_ACCESS_EDITION_PATH}`);
await page.getByTestId(LOGIN_TO_READ_TEST_ID).click();
await page.waitForURL(`**${NYPL_LOGIN_URL}**`);
const url = new URL(page.url());
const redirectUri = url.searchParams.get("redirect_uri");

expect(redirectUri).toContain(LIMITED_ACCESS_WORK_PATH);
expect(redirectUri).toContain(LIMITED_ACCESS_EDITION_PATH);
});

test("redirects to NYPL login page with expired cookie", async ({
page,
port,
setCookie,
}) => {
const cookieExpiration = new Date("1970-01-01T00:00:00.000Z").getTime();
setCookie(cookieExpiration);

await page.goto(`http://localhost:${port}${LIMITED_ACCESS_WORK_PATH}`);
await page.getByRole("link", { name: "title Download PDF" }).click();
await page.goto(`${LIMITED_ACCESS_EDITION_PATH}`);
await page.getByTestId(LOGIN_TO_READ_TEST_ID).click();
await page.waitForURL(`**${NYPL_LOGIN_URL}**`);
const url = new URL(page.url());
const redirectUri = url.searchParams.get("redirect_uri");

expect(redirectUri).toContain(LIMITED_ACCESS_WORK_PATH);
expect(redirectUri).toContain(LIMITED_ACCESS_EDITION_PATH);
});

test("redirects to download with valid auth cookie", async ({
// TODO: logging in from localhost does not work
test.skip("redirects to download with valid auth cookie", async ({
page,
port,
setCookie,
context,
}) => {
Expand All @@ -58,7 +55,7 @@ test.describe("Cookie authentication", () => {

expect(authCookie.path).toBe("/");

await page.goto(`http://localhost:${port}${LIMITED_ACCESS_WORK_PATH}`);
await page.goto(`${LIMITED_ACCESS_EDITION_PATH}`);

const responsePromise = page.waitForResponse(`${API_URL}${FULFILL_PATH}`);
await page.getByRole("link", { name: "title Download PDF" }).click();
Expand Down
37 changes: 14 additions & 23 deletions playwright/integration/landing.spec.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,24 @@
import { test, expect } from "../support/test-utils";
import {
INVALID_COLLECTION_PATH,
HOME_PATH,
COLLECTION_PATH,
} from "~/mocks/mockEnv";
import { INVALID_COLLECTION_PATH, HOME_PATH } from "~/mocks/mockEnv";
import { server } from "~/mocks/server";
import {
SEARCH_BAR_TEST_ID,
ERROR_LAYOUT_TEST_ID,
} from "~/src/constants/testIds";

test.afterEach(() => server.resetHandlers());
test.afterAll(() => server.close());

test("View landing page with collection", async ({ page, port }) => {
await page.goto(`http://localhost:${port}${HOME_PATH}`);
const collectionHeading = page.getByRole("heading", {
name: "Recently Added Collections",
level: 2,
});
expect(collectionHeading).toBeVisible();
const collectionLink = await page
.getByRole("link", {
name: /Baseball: A Collection by Mike Benowitz/,
})
.getAttribute("href");
expect(collectionLink).toContain(COLLECTION_PATH);
test("View landing page with search", async ({ page }) => {
await page.goto(`${HOME_PATH}`);

const searchBar = page.getByTestId(SEARCH_BAR_TEST_ID);
await expect(searchBar).toBeVisible();
});

test("Shows error boundary for invalid collection", async ({ page, port }) => {
await page.goto(`http://localhost:${port}${INVALID_COLLECTION_PATH}`);
test("Shows error page for invalid collection", async ({ page }) => {
await page.goto(`${INVALID_COLLECTION_PATH}`);

const alert = page.getByRole("alert");
const errorText = alert.getByText("Something went wrong on our end");
await expect(errorText).toBeVisible();
const errorLayout = page.getByTestId(ERROR_LAYOUT_TEST_ID);
await expect(errorLayout).toBeVisible();
});
3 changes: 2 additions & 1 deletion src/components/EditionCard/DownloadLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { trackCtaClick } from "~/src/lib/adobe/Analytics";
import { fulfillFetcher } from "~/src/lib/api/SearchApi";
import { ItemLink } from "~/src/types/DataModel";
import { formatUrl } from "~/src/util/Util";
import { LOGIN_TO_DOWNLOAD_TEST_ID } from "~/src/constants/testIds";

const DownloadLink: React.FC<{
downloadLink: ItemLink;
Expand Down Expand Up @@ -73,7 +74,7 @@ const DownloadLink: React.FC<{
}

return (
<Box>
<Box data-testid={LOGIN_TO_DOWNLOAD_TEST_ID}>
<Link
to={`${linkUrl}`}
linkType="buttonSecondary"
Expand Down
3 changes: 2 additions & 1 deletion src/components/EditionCard/ReadOnlineLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from "react";
import Link from "~/src/components/Link/Link";
import { LOGIN_LINK_BASE } from "~/src/constants/links";
import { ItemLink } from "~/src/types/DataModel";
import { LOGIN_TO_READ_TEST_ID } from "~/src/constants/testIds";

// "Read Online" button should only show up if the link was flagged as "reader" or "embed"
const ReadOnlineLink: React.FC<{
Expand All @@ -27,7 +28,7 @@ const ReadOnlineLink: React.FC<{

return (
readOnlineLink && (
<Box>
<Box data-testid={LOGIN_TO_READ_TEST_ID}>
<Link
to={linkUrl}
linkType="button"
Expand Down
2 changes: 2 additions & 0 deletions src/components/SearchForm/SearchForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { ChangeEvent, useState } from "react";
import { useRouter } from "next/router";
import { SearchBar, Box } from "@nypl/design-system-react-components";
import { SEARCH_BAR_TEST_ID } from "~/src/constants/testIds";
import { SearchQuery, SearchQueryDefaults } from "~/src/types/SearchQuery";
import { errorMessagesText, inputTerms } from "~/src/constants/labels";
import { toLocationQuery, toApiQuery } from "~/src/util/apiConversion";
Expand Down Expand Up @@ -89,6 +90,7 @@ const SearchForm: React.FC<{
onChange: (e) => onQueryChange(e),
}}
labelText="Search"
data-testid={SEARCH_BAR_TEST_ID}
/>
<Box float="right" marginTop={{ md: "xs" }}>
<Link to="/advanced-search" isUnderlined={false}>
Expand Down
4 changes: 4 additions & 0 deletions src/constants/testIds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const SEARCH_BAR_TEST_ID = "search-bar";
export const ERROR_LAYOUT_TEST_ID = "error-layout";
export const LOGIN_TO_READ_TEST_ID = "login-to-read";
export const LOGIN_TO_DOWNLOAD_TEST_ID = "login-to-download";
2 changes: 2 additions & 0 deletions src/pages/_error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Text,
} from "@nypl/design-system-react-components";
import { FeedbackContext } from "../context/FeedbackContext";
import { ERROR_LAYOUT_TEST_ID } from "../constants/testIds";

const ERROR_PERSISTS = " if the error persists.";

Expand Down Expand Up @@ -58,6 +59,7 @@ const Error = ({ statusCode }) => {
paddingRight="l"
textAlign="center"
role="alert"
data-testid={ERROR_LAYOUT_TEST_ID}
>
<Image
src="/images/error-img.png"
Expand Down
Loading