From 2de1615a0959076a9a2c6f70c8b22aca8f2f8779 Mon Sep 17 00:00:00 2001 From: Charles Date: Thu, 22 Jul 2021 10:43:36 +1000 Subject: [PATCH] Example/custom logo example (#6145) * init * guides for custom page and custom components * more examples commits * yarn.lock and example changes * dependency fix * add more markup * Update docs/pages/docs/guides/custom-admin-ui-pages.mdx Co-authored-by: Mitchell Hamilton * fix readme * more updates to the docs * add smoke tests * add to smoke tests in workflow * fill in links * add new guides to docs nav * fix docs * fix readME.md * changelog reset * add examples link to docs and README.md * update explanation of Old JSX transforms * change custom-admin-ui-components example to custom-admin-ui-logo * Update docs/pages/docs/guides/custom-admin-ui-pages.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-pages.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-pages.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-pages.mdx Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-pages/README.md Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-pages/README.md Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-components/README.md Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-components.mdx Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-pages/admin/pages/custom-page.tsx Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-components/README.md Co-authored-by: Tim Leslie * add CTA to give us feedback on admin-ui components in slack * fix up odds and ends in formatting for docs pages * Update docs/pages/docs/guides/custom-admin-ui-logo.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-logo.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-pages.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-pages.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-pages.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-logo.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-logo.mdx Co-authored-by: Tim Leslie * Feedback from Tim * add image * Update examples/README.md Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-logo/README.md Co-authored-by: Tim Leslie * remove custom-page artifacts, so we can just ship the custom-logo guides for now * dependency resolution * update schema.graphql; * Update examples/README.md Co-authored-by: Tim Leslie * Update docs/components/docs/Navigation.tsx Co-authored-by: Tim Leslie * Update docs/components/docs/ExamplesList.tsx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-logo.mdx Co-authored-by: Tim Leslie * Update docs/pages/docs/guides/custom-admin-ui-logo.mdx Co-authored-by: Tim Leslie * update broken image link * remove admin-ui pages test * Update examples/custom-admin-ui-logo/admin/components/CustomLogo.tsx Co-authored-by: Tim Leslie * add chnageset * Update examples/custom-admin-ui-logo/README.md Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-logo/README.md Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-logo/README.md Co-authored-by: Tim Leslie * Update examples/custom-admin-ui-logo/README.md Co-authored-by: Tim Leslie Co-authored-by: Mitchell Hamilton Co-authored-by: Tim Leslie --- .changeset/slimy-moons-grow.md | 5 + .github/workflows/tests.yml | 1 + docs/components/docs/ExamplesList.tsx | 9 + docs/components/docs/Navigation.tsx | 6 +- .../docs/guides/custom-admin-ui-logo.mdx | 49 +++ .../docs/guides/custom-admin-ui-pages.mdx | 8 - .../custom-logo-result.png | Bin 0 -> 98153 bytes examples/README.md | 1 + examples/custom-admin-ui-logo/CHANGELOG.md | 1 + examples/custom-admin-ui-logo/README.md | 28 ++ .../admin/components/CustomLogo.tsx | 26 ++ .../custom-admin-ui-logo/admin/config.tsx | 7 + examples/custom-admin-ui-logo/keystone.ts | 11 + examples/custom-admin-ui-logo/package.json | 26 ++ examples/custom-admin-ui-logo/schema.graphql | 359 ++++++++++++++++++ examples/custom-admin-ui-logo/schema.prisma | 27 ++ examples/custom-admin-ui-logo/schema.ts | 28 ++ .../custom-admin-ui-logo.test.ts | 19 + 18 files changed, 600 insertions(+), 11 deletions(-) create mode 100644 .changeset/slimy-moons-grow.md create mode 100644 docs/pages/docs/guides/custom-admin-ui-logo.mdx delete mode 100644 docs/pages/docs/guides/custom-admin-ui-pages.mdx create mode 100644 docs/public/assets/guides/custom-admin-ui-logo/custom-logo-result.png create mode 100644 examples/custom-admin-ui-logo/CHANGELOG.md create mode 100644 examples/custom-admin-ui-logo/README.md create mode 100644 examples/custom-admin-ui-logo/admin/components/CustomLogo.tsx create mode 100644 examples/custom-admin-ui-logo/admin/config.tsx create mode 100644 examples/custom-admin-ui-logo/keystone.ts create mode 100644 examples/custom-admin-ui-logo/package.json create mode 100644 examples/custom-admin-ui-logo/schema.graphql create mode 100644 examples/custom-admin-ui-logo/schema.prisma create mode 100644 examples/custom-admin-ui-logo/schema.ts create mode 100644 tests/examples-smoke-tests/custom-admin-ui-logo.test.ts diff --git a/.changeset/slimy-moons-grow.md b/.changeset/slimy-moons-grow.md new file mode 100644 index 00000000000..da3e9bd743e --- /dev/null +++ b/.changeset/slimy-moons-grow.md @@ -0,0 +1,5 @@ +--- +'@keystone-next/example-custom-admin-ui-logo': major +--- + +Initial version of the custom-admin-ui-logo example. diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a06079f1d08..a005679387d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -261,6 +261,7 @@ jobs: 'with-auth.test.ts', 'custom-field-view.test.ts', 'custom-field.test.ts', + 'custom-admin-ui-logo.test.ts', ] fail-fast: false steps: diff --git a/docs/components/docs/ExamplesList.tsx b/docs/components/docs/ExamplesList.tsx index 9ddf13fb630..d9658f03efe 100644 --- a/docs/components/docs/ExamplesList.tsx +++ b/docs/components/docs/ExamplesList.tsx @@ -123,6 +123,15 @@ export function Examples() { Adds a custom field type based on the integer field type which lets users rate items on a 5-star scale. Builds on the Blog starter project. + + Adds a custom logo component in the Admin UI. Builds on the Task Manager starter project. + ); } diff --git a/docs/components/docs/Navigation.tsx b/docs/components/docs/Navigation.tsx index 89262e155d4..fe4f5ff0702 100644 --- a/docs/components/docs/Navigation.tsx +++ b/docs/components/docs/Navigation.tsx @@ -144,6 +144,9 @@ export function DocsNavigation() { Custom Fields New + + Custom Admin UI Logo New + Access Control @@ -156,9 +159,6 @@ export function DocsNavigation() { Internal Items - - Custom Admin UI Pages - Custom Field Views diff --git a/docs/pages/docs/guides/custom-admin-ui-logo.mdx b/docs/pages/docs/guides/custom-admin-ui-logo.mdx new file mode 100644 index 00000000000..623b0f8d962 --- /dev/null +++ b/docs/pages/docs/guides/custom-admin-ui-logo.mdx @@ -0,0 +1,49 @@ +import { ComingSoon } from '../../../components/docs/ComingSoon'; +import { Markdown } from '../../../components/Markdown'; +import { Alert } from '../../../components/primitives/Alert' + +# Custom Admin UI Logo + +In this guide we'll show you how to add a custom logo to the Keystone Admin UI. + +!> Presently the only replaceable component in the Admin UI is the logo. If you have suggestions as to other components you would like to be able to customise, let us know on [Slack](https://community.keystonejs.com) + +To import a custom component for rendering within the Admin UI, ensure that the `admin/config.tsx` file exists in the root of your Keystone project. +This file expects a named export `components`. + +```tsx +// admin/config.tsx +function CustomLogo () { + return

Custom Logo here

+} + +export const components = { + Logo: CustomLogo +} +``` + +If you have styling constraints, we recommend using the jsx export from the `@keystone-ui/core` package, as this will ensure that the version of emotion you're using conforms with the version of emotion used internally within Keystone. + +```tsx +// admin/config.tsx +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@keystone-ui/core'; + +function CustomLogo () { + return

Custom Logo here

+} + +export const components = { + Logo: CustomLogo +} +``` + +Of course this is purely a recommendation, if you would prefer to roll your own css-in-js solution in with your custom component please feel free to! Although this may require additional configuration outside of the scope of this guide. + +Once you've added your custom logo component you should see it rendered out in the Admin UI. +![image of Admin UI with custom logo](/assets/guides/custom-admin-ui-logo/custom-logo-result.png) + +export default ({ children }) => {children}; diff --git a/docs/pages/docs/guides/custom-admin-ui-pages.mdx b/docs/pages/docs/guides/custom-admin-ui-pages.mdx deleted file mode 100644 index f8e2e6b40bb..00000000000 --- a/docs/pages/docs/guides/custom-admin-ui-pages.mdx +++ /dev/null @@ -1,8 +0,0 @@ -import { ComingSoon } from '../../../components/docs/ComingSoon'; -import { Markdown } from '../../../components/Markdown'; - -# Custom Admin UI Pages - - - -export default ({ children }) => {children}; diff --git a/docs/public/assets/guides/custom-admin-ui-logo/custom-logo-result.png b/docs/public/assets/guides/custom-admin-ui-logo/custom-logo-result.png new file mode 100644 index 0000000000000000000000000000000000000000..b3cc32317650feb60d178facb7d440e0468264f0 GIT binary patch literal 98153 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 { + return ( +

+ + + LegendBoulder After + + +

+ ); +}; diff --git a/examples/custom-admin-ui-logo/admin/config.tsx b/examples/custom-admin-ui-logo/admin/config.tsx new file mode 100644 index 00000000000..d5e845d1013 --- /dev/null +++ b/examples/custom-admin-ui-logo/admin/config.tsx @@ -0,0 +1,7 @@ +import { AdminConfig } from '@keystone-next/types'; +import { CustomLogo } from './components/CustomLogo'; + +// Presently the Logo is the only Admin UI component that is customisable. +export const components: AdminConfig['components'] = { + Logo: CustomLogo, +}; diff --git a/examples/custom-admin-ui-logo/keystone.ts b/examples/custom-admin-ui-logo/keystone.ts new file mode 100644 index 00000000000..a74fdce21b4 --- /dev/null +++ b/examples/custom-admin-ui-logo/keystone.ts @@ -0,0 +1,11 @@ +import { config } from '@keystone-next/keystone/schema'; +import { lists } from './schema'; + +export default config({ + db: { + provider: 'sqlite', + url: process.env.DATABASE_URL || 'file:./keystone-example.db', + }, + lists, + ui: {}, +}); diff --git a/examples/custom-admin-ui-logo/package.json b/examples/custom-admin-ui-logo/package.json new file mode 100644 index 00000000000..9eebcada407 --- /dev/null +++ b/examples/custom-admin-ui-logo/package.json @@ -0,0 +1,26 @@ +{ + "name": "@keystone-next/example-custom-admin-ui-logo", + "version": "0.0.1", + "private": true, + "license": "MIT", + "scripts": { + "dev": "keystone-next dev", + "start": "keystone-next start", + "build": "keystone-next build" + }, + "dependencies": { + "@keystone-next/fields": "^12.0.0", + "@keystone-next/keystone": "^22.0.0", + "@keystone-next/types": "^22.0.0", + "@keystone-ui/core": "^3.1.0", + "next": "^10.2.3", + "react": "^17.0.2" + }, + "devDependencies": { + "typescript": "^4.3.5" + }, + "engines": { + "node": "^12.20 || >= 14.13" + }, + "repository": "https://github.com/keystonejs/keystone/tree/master/examples/custom-admin-ui-logo" +} diff --git a/examples/custom-admin-ui-logo/schema.graphql b/examples/custom-admin-ui-logo/schema.graphql new file mode 100644 index 00000000000..4b82d494eec --- /dev/null +++ b/examples/custom-admin-ui-logo/schema.graphql @@ -0,0 +1,359 @@ +type Task { + id: ID! + label: String + priority: TaskPriorityType + isComplete: Boolean + assignedTo: Person + finishBy: String +} + +enum TaskPriorityType { + low + medium + high +} + +input TaskWhereInput { + AND: [TaskWhereInput!] + OR: [TaskWhereInput!] + id: ID + id_not: ID + id_lt: ID + id_lte: ID + id_gt: ID + id_gte: ID + id_in: [ID!] + id_not_in: [ID!] + label: String + label_not: String + label_contains: String + label_not_contains: String + label_in: [String] + label_not_in: [String] + priority: TaskPriorityType + priority_not: TaskPriorityType + priority_in: [TaskPriorityType] + priority_not_in: [TaskPriorityType] + isComplete: Boolean + isComplete_not: Boolean + assignedTo: PersonWhereInput + assignedTo_is_null: Boolean + finishBy: String + finishBy_not: String + finishBy_lt: String + finishBy_lte: String + finishBy_gt: String + finishBy_gte: String + finishBy_in: [String] + finishBy_not_in: [String] +} + +input TaskWhereUniqueInput { + id: ID +} + +enum SortTasksBy { + id_ASC + id_DESC + label_ASC + label_DESC + priority_ASC + priority_DESC + isComplete_ASC + isComplete_DESC + finishBy_ASC + finishBy_DESC +} + +input TaskOrderByInput { + id: OrderDirection + label: OrderDirection + priority: OrderDirection + isComplete: OrderDirection + finishBy: OrderDirection +} + +enum OrderDirection { + asc + desc +} + +input TaskUpdateInput { + label: String + priority: TaskPriorityType + isComplete: Boolean + assignedTo: PersonRelateToOneInput + finishBy: String +} + +input PersonRelateToOneInput { + create: PersonCreateInput + connect: PersonWhereUniqueInput + disconnect: PersonWhereUniqueInput + disconnectAll: Boolean +} + +input TasksUpdateInput { + id: ID! + data: TaskUpdateInput +} + +input TaskCreateInput { + label: String + priority: TaskPriorityType + isComplete: Boolean + assignedTo: PersonRelateToOneInput + finishBy: String +} + +input TasksCreateInput { + data: TaskCreateInput +} + +type Person { + id: ID! + name: String + tasks( + where: TaskWhereInput! = {} + search: String + sortBy: [SortTasksBy!] + @deprecated(reason: "sortBy has been deprecated in favour of orderBy") + orderBy: [TaskOrderByInput!]! = [] + first: Int + skip: Int! = 0 + ): [Task!] + _tasksMeta( + where: TaskWhereInput! = {} + search: String + sortBy: [SortTasksBy!] + @deprecated(reason: "sortBy has been deprecated in favour of orderBy") + orderBy: [TaskOrderByInput!]! = [] + first: Int + skip: Int! = 0 + ): _QueryMeta + @deprecated( + reason: "This query will be removed in a future version. Please use tasksCount instead." + ) + tasksCount(where: TaskWhereInput! = {}): Int +} + +type _QueryMeta { + count: Int +} + +input PersonWhereInput { + AND: [PersonWhereInput!] + OR: [PersonWhereInput!] + id: ID + id_not: ID + id_lt: ID + id_lte: ID + id_gt: ID + id_gte: ID + id_in: [ID!] + id_not_in: [ID!] + name: String + name_not: String + name_contains: String + name_not_contains: String + name_in: [String] + name_not_in: [String] + tasks_every: TaskWhereInput + tasks_some: TaskWhereInput + tasks_none: TaskWhereInput +} + +input PersonWhereUniqueInput { + id: ID +} + +enum SortPeopleBy { + id_ASC + id_DESC + name_ASC + name_DESC +} + +input PersonOrderByInput { + id: OrderDirection + name: OrderDirection +} + +input PersonUpdateInput { + name: String + tasks: TaskRelateToManyInput +} + +input TaskRelateToManyInput { + create: [TaskCreateInput] + connect: [TaskWhereUniqueInput] + disconnect: [TaskWhereUniqueInput] + disconnectAll: Boolean +} + +input PeopleUpdateInput { + id: ID! + data: PersonUpdateInput +} + +input PersonCreateInput { + name: String + tasks: TaskRelateToManyInput +} + +input PeopleCreateInput { + data: PersonCreateInput +} + +""" +The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf). +""" +scalar JSON + @specifiedBy( + url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf" + ) + +type Mutation { + createTask(data: TaskCreateInput): Task + createTasks(data: [TasksCreateInput]): [Task] + updateTask(id: ID!, data: TaskUpdateInput): Task + updateTasks(data: [TasksUpdateInput]): [Task] + deleteTask(id: ID!): Task + deleteTasks(ids: [ID!]): [Task] + createPerson(data: PersonCreateInput): Person + createPeople(data: [PeopleCreateInput]): [Person] + updatePerson(id: ID!, data: PersonUpdateInput): Person + updatePeople(data: [PeopleUpdateInput]): [Person] + deletePerson(id: ID!): Person + deletePeople(ids: [ID!]): [Person] +} + +type Query { + allTasks( + where: TaskWhereInput! = {} + search: String + sortBy: [SortTasksBy!] + @deprecated(reason: "sortBy has been deprecated in favour of orderBy") + orderBy: [TaskOrderByInput!]! = [] + first: Int + skip: Int! = 0 + ): [Task!] + Task(where: TaskWhereUniqueInput!): Task + _allTasksMeta( + where: TaskWhereInput! = {} + search: String + sortBy: [SortTasksBy!] + @deprecated(reason: "sortBy has been deprecated in favour of orderBy") + orderBy: [TaskOrderByInput!]! = [] + first: Int + skip: Int! = 0 + ): _QueryMeta + @deprecated( + reason: "This query will be removed in a future version. Please use tasksCount instead." + ) + tasksCount(where: TaskWhereInput! = {}): Int + allPeople( + where: PersonWhereInput! = {} + search: String + sortBy: [SortPeopleBy!] + @deprecated(reason: "sortBy has been deprecated in favour of orderBy") + orderBy: [PersonOrderByInput!]! = [] + first: Int + skip: Int! = 0 + ): [Person!] + Person(where: PersonWhereUniqueInput!): Person + _allPeopleMeta( + where: PersonWhereInput! = {} + search: String + sortBy: [SortPeopleBy!] + @deprecated(reason: "sortBy has been deprecated in favour of orderBy") + orderBy: [PersonOrderByInput!]! = [] + first: Int + skip: Int! = 0 + ): _QueryMeta + @deprecated( + reason: "This query will be removed in a future version. Please use peopleCount instead." + ) + peopleCount(where: PersonWhereInput! = {}): Int + keystone: KeystoneMeta! +} + +type KeystoneMeta { + adminMeta: KeystoneAdminMeta! +} + +type KeystoneAdminMeta { + enableSignout: Boolean! + enableSessionItem: Boolean! + lists: [KeystoneAdminUIListMeta!]! + list(key: String!): KeystoneAdminUIListMeta +} + +type KeystoneAdminUIListMeta { + key: String! + itemQueryName: String! + listQueryName: String! + hideCreate: Boolean! + hideDelete: Boolean! + path: String! + label: String! + singular: String! + plural: String! + description: String + initialColumns: [String!]! + pageSize: Int! + labelField: String! + fields: [KeystoneAdminUIFieldMeta!]! + initialSort: KeystoneAdminUISort + isHidden: Boolean! +} + +type KeystoneAdminUIFieldMeta { + path: String! + label: String! + isOrderable: Boolean! + fieldMeta: JSON + viewsIndex: Int! + customViewsIndex: Int + createView: KeystoneAdminUIFieldMetaCreateView! + listView: KeystoneAdminUIFieldMetaListView! + itemView(id: ID!): KeystoneAdminUIFieldMetaItemView +} + +type KeystoneAdminUIFieldMetaCreateView { + fieldMode: KeystoneAdminUIFieldMetaCreateViewFieldMode! +} + +enum KeystoneAdminUIFieldMetaCreateViewFieldMode { + edit + hidden +} + +type KeystoneAdminUIFieldMetaListView { + fieldMode: KeystoneAdminUIFieldMetaListViewFieldMode! +} + +enum KeystoneAdminUIFieldMetaListViewFieldMode { + read + hidden +} + +type KeystoneAdminUIFieldMetaItemView { + fieldMode: KeystoneAdminUIFieldMetaItemViewFieldMode! +} + +enum KeystoneAdminUIFieldMetaItemViewFieldMode { + edit + read + hidden +} + +type KeystoneAdminUISort { + field: String! + direction: KeystoneAdminUISortDirection! +} + +enum KeystoneAdminUISortDirection { + ASC + DESC +} diff --git a/examples/custom-admin-ui-logo/schema.prisma b/examples/custom-admin-ui-logo/schema.prisma new file mode 100644 index 00000000000..a1efaced2f7 --- /dev/null +++ b/examples/custom-admin-ui-logo/schema.prisma @@ -0,0 +1,27 @@ +datasource sqlite { + url = env("DATABASE_URL") + provider = "sqlite" +} + +generator client { + provider = "prisma-client-js" + output = "node_modules/.prisma/client" +} + +model Task { + id String @id @default(cuid()) + label String? + priority String? + isComplete Boolean? + assignedTo Person? @relation("Task_assignedTo", fields: [assignedToId], references: [id]) + assignedToId String? @map("assignedTo") + finishBy DateTime? + + @@index([assignedToId]) +} + +model Person { + id String @id @default(cuid()) + name String? + tasks Task[] @relation("Task_assignedTo") +} \ No newline at end of file diff --git a/examples/custom-admin-ui-logo/schema.ts b/examples/custom-admin-ui-logo/schema.ts new file mode 100644 index 00000000000..9b539803be8 --- /dev/null +++ b/examples/custom-admin-ui-logo/schema.ts @@ -0,0 +1,28 @@ +import { createSchema, list } from '@keystone-next/keystone/schema'; +import { checkbox, relationship, text, timestamp } from '@keystone-next/fields'; +import { select } from '@keystone-next/fields'; + +export const lists = createSchema({ + Task: list({ + fields: { + label: text({ isRequired: true }), + priority: select({ + dataType: 'enum', + options: [ + { label: 'Low', value: 'low' }, + { label: 'Medium', value: 'medium' }, + { label: 'High', value: 'high' }, + ], + }), + isComplete: checkbox(), + assignedTo: relationship({ ref: 'Person.tasks', many: false }), + finishBy: timestamp(), + }, + }), + Person: list({ + fields: { + name: text({ isRequired: true }), + tasks: relationship({ ref: 'Task.assignedTo', many: true }), + }, + }), +}); diff --git a/tests/examples-smoke-tests/custom-admin-ui-logo.test.ts b/tests/examples-smoke-tests/custom-admin-ui-logo.test.ts new file mode 100644 index 00000000000..6942b52a0a3 --- /dev/null +++ b/tests/examples-smoke-tests/custom-admin-ui-logo.test.ts @@ -0,0 +1,19 @@ +import { Browser, Page } from 'playwright'; +import { exampleProjectTests } from './utils'; + +exampleProjectTests('custom-admin-ui-logo', browserType => { + let browser: Browser = undefined as any; + let page: Page = undefined as any; + beforeAll(async () => { + browser = await browserType.launch(); + page = await browser.newPage(); + await page.goto('http://localhost:3000'); + }); + test('Find custom logo', async () => { + const content = await page.textContent('h3 a'); + expect(content).toBe('LegendBoulder After'); + }); + afterAll(async () => { + await browser.close(); + }); +});