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

UPSE-386: Update Playwright search tests for 'favorite' flag #648

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
43 changes: 43 additions & 0 deletions tests/api/search-v5_0.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,28 @@
import { test, expect } from "@playwright/test";
import { config } from "../general-config";
import { loginViaApi } from "../ux/utils/ux-general-utils";
import {
PortletDefBasicInfo,
getPortletDetails,
} from "./utils/api-portlets-utils";
import {
favoritePortlet,
unfavoritePortlet,
} from "./utils/api-preferences-utils";

interface PortletSearchResult {
description: string;
fname: string;
name: string;
score: string;
title: string;
url: string;
favorite: boolean;
}

interface PortletSearchResults {
portlets: PortletSearchResult[];
}
Comment on lines +13 to +25
Copy link
Member

Choose a reason for hiding this comment

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

Completely optional, but if you are interested in trying Zod.
This would look something like:

import z from 'zod';

const PortletSearchResultSchema = z.object({
  description: z.string(),
  fname: z.string(),
  name: z.string(),
  score: z.string(),
  title: z.string(),
  url: z.string(),
  favorite: z.boolean();
});
type PortletSearchResult = z.infer<typeof PortletSearchResultSchema>;

const PortletSearchResultsSchema = z.object({
  portlets: z.array(PortletSearchResultSchema)
});
type PortletSearchResults = z.infer<typeof PortletSearchResultsSchema>

this could later be used:

const portletSearchResults: PortletSearchResults = PortletSearchResultsSchema.parse(JSON.parse(await response.text()));


test("search all", async ({ request }) => {
await loginViaApi(request, config.users.admin);
Expand All @@ -18,11 +40,32 @@ test("search all", async ({ request }) => {
score: "4.0",
title: "Daily Business Cartoon",
url: "/uPortal/p/daily-business-cartoon.ctf3/max/render.uP",
favorite: false,
},
],
});
});

test("search favorited portlet", async({ request }) => {
await loginViaApi(request, config.users.admin);
const portletFname = 'daily-business-cartoon';
const portletDetails: PortletDefBasicInfo | null = await getPortletDetails(request, portletFname);
if (!portletDetails) {
console.error('could not retrieve portlet details in order to get portlet ID');
test.fail();
} else {
const portletId = portletDetails.id;
expect(await favoritePortlet(request, portletId)).not.toBeNull();
const response = await request.get(`${config.url}api/v5-0/portal/search?q=cartoon&type=portlets`);
expect(await unfavoritePortlet(request, portletId)).toBe(true);
expect(response.status()).toEqual(200);
const portletSearchResults: PortletSearchResults = JSON.parse(await response.text()) as PortletSearchResults;
Copy link
Member

Choose a reason for hiding this comment

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

an as cast is probably fine for a test case.
Using a JSON parser/validator like zod would give better assurance that the structure returns matches the test expectation. https://zod.dev/

const portletFound: PortletSearchResult = portletSearchResults.portlets[0];
expect(portletFound.favorite).toBe(true);
expect(portletFound.fname).toBe(portletFname);
}
});

test("search type people", async ({ request }) => {
await loginViaApi(request, config.users.admin);
const response = await request.get(
Expand Down
32 changes: 32 additions & 0 deletions tests/api/utils/api-portlets-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expect, APIRequestContext } from "@playwright/test";
import { config } from "../../general-config";

export interface PortletDefBasicInfo {
id: string;
name: string;
fname: string;
}

interface PortletsResponse {
portlets: PortletDefBasicInfo[];
}

/*
* Retrieve the details for a portlet identified by it's fname.
*/
export async function getPortletDetails(
request: APIRequestContext,
portletFname: string
): Promise<PortletDefBasicInfo | null> {
const response = await request.get(`${config.url}api/portlets.json`);
expect(response.status()).toEqual(200);
const portletsJson: PortletsResponse = await response.json() as PortletsResponse;
Copy link
Member

Choose a reason for hiding this comment

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

it would be nice if we parsed/validated the JSON.

const portlets: PortletDefBasicInfo[] = portletsJson.portlets;
for (const val of portlets) {
if (val != null && val.fname == portletFname) {
return val;
}
}
return null;
}

37 changes: 37 additions & 0 deletions tests/api/utils/api-preferences-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { expect, APIRequestContext } from "@playwright/test";
import { config } from "../../general-config";

interface PreferenceFavoriteResponse {
newNodeId: string;
response: string;
}

/*
* Favorite a portlet, indentified by portlet ID. Return new node ID.
*/
export async function favoritePortlet(
request: APIRequestContext,
portletId: string
): Promise<string> {
expect(portletId).not.toBeNull();
const response = await request.post(
`${config.url}api/layout?action=addFavorite&channelId=${portletId}`
);
expect(response.status()).toEqual(200);
const responseBody: PreferenceFavoriteResponse = JSON.parse(await response.text()) as PreferenceFavoriteResponse;
Copy link
Member

Choose a reason for hiding this comment

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

it would be nice if we parsed/validated the JSON.

return responseBody.newNodeId;
}

/*
* Unfavorite a portlet, indentified by portlet ID. Returns boolean indicating whether or not operation was successful.
*/
export async function unfavoritePortlet(
request: APIRequestContext,
portletId: string
): Promise<boolean> {
expect(portletId).not.toBeNull();
const response = await request.post(`${config.url}api/layout?action=removeFavorite&channelId=${portletId}`);
expect(response.status()).toEqual(200);
const responseBody: PreferenceFavoriteResponse = JSON.parse(await response.text()) as PreferenceFavoriteResponse;
Copy link
Member

Choose a reason for hiding this comment

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

it would be nice if we parsed/validated the JSON.

return responseBody.response === "Removed from Favorites successfully";
}