Skip to content

Commit

Permalink
ci(playwright): write e2e test for nested themes
Browse files Browse the repository at this point in the history
- write e2e test for nested theme overriding
- update test repo to allow for nested theme nodes
- update snapshots
  • Loading branch information
RyanClementsHax committed Nov 5, 2023
1 parent 4a763f2 commit cdef1c6
Show file tree
Hide file tree
Showing 50 changed files with 136 additions and 17 deletions.
4 changes: 2 additions & 2 deletions e2e/test_repos/templates/create-react-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ function App() {
</header>
<main className="mx-auto mt-8 flex w-[75ch] flex-col items-center gap-8">
{Array.from({ length: numThemeNodes }, (_, i) => {
const nodeId = i + 1
const nodeId = (i + 1).toString()
return <ThemeNode key={nodeId} nodeId={nodeId} />
})}
<button
className="rounded-md border-0 bg-white px-4 py-3 shadow-md ring-inset ring-slate-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 focus-visible:outline-none"
className="rounded-md border-0 bg-white px-4 py-3 shadow-md ring-inset hover:ring-2 hover:ring-inset hover:ring-indigo-600 focus:ring-2 focus:ring-inset focus:ring-indigo-600 focus-visible:outline-none active:bg-indigo-300"
onClick={() => setNumThemeNodes(num => num + 1)}
>
Add theme node
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useMemo, useRef, useState } from 'react'

export interface ThemeNodeProps {
nodeId: number
nodeId: string
}

export function ThemeNode({ nodeId }: ThemeNodeProps) {
const [parsedAttributes, attributesInput, setAttributesInput] =
useParsedAttributes()
const [numThemeNodes, setNumThemeNodes] = useState(0)
return (
<section
data-testid={`theme-node-${nodeId}`}
Expand All @@ -20,7 +21,17 @@ export function ThemeNode({ nodeId }: ThemeNodeProps) {
parsedAttributes={parsedAttributes}
/>
<hr />
<ThemedContent attributes={parsedAttributes} />
<ThemedContent
attributes={parsedAttributes}
nodeId={nodeId}
numThemeNodes={numThemeNodes}
/>
<button
className="self-start rounded-md border-0 px-4 py-3 shadow-md ring-1 ring-inset ring-slate-300 hover:ring-2 hover:ring-inset hover:ring-indigo-600 focus:ring-2 focus:ring-inset focus:ring-indigo-600 focus-visible:outline-none active:bg-indigo-300"
onClick={() => setNumThemeNodes(num => num + 1)}
>
Add theme node to {nodeId}
</button>
</section>
)
}
Expand Down Expand Up @@ -50,7 +61,7 @@ const useParsedAttributes = (): [
}

interface AttributesInputProps {
nodeId: number
nodeId: string
attributesInput: string
setAttributesInput: (input: string) => void
parsedAttributes: Record<string, string>
Expand Down Expand Up @@ -85,16 +96,28 @@ function AttributesInput({
}

interface ThemedContentProps {
nodeId: string
numThemeNodes: number
attributes: Record<string, string>
}

function ThemedContent({ attributes }: ThemedContentProps) {
function ThemedContent({
attributes,
numThemeNodes,
nodeId
}: ThemedContentProps) {
return (
<div className="flex flex-col gap-2 text-sm">
Themed content
<div className="rounded-md border border-slate-200 p-5">
<div className="rounded-md bg-indigo-50 p-5">
<div {...attributes}>
<div className="bg-primary h-10 w-10 rounded-md"></div>
<div className="flex flex-col gap-5">
<div className="bg-primary h-10 w-10 rounded-md"></div>
{Array.from({ length: numThemeNodes }, (_, i) => {
const childNodeId = `${nodeId}.${i + 1}`
return <ThemeNode key={childNodeId} nodeId={childNodeId} />
})}
</div>
</div>
</div>
</div>
Expand Down
34 changes: 26 additions & 8 deletions e2e/test_repos/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface ThemeNode {
setClass(className: string): Promise<void>
removeClass(className: string): Promise<void>
setAttribute(key: string, value: string): Promise<void>
createNode(): Promise<ThemeNode>
}

export const test = base.extend<{ testRepo: TestRepo }>({
Expand All @@ -30,9 +31,9 @@ export const test = base.extend<{ testRepo: TestRepo }>({
return this.createNode()
},
async createNode() {
await page.getByRole('button', { name: /add theme node/i }).click()
await page.getByRole('button', { name: /^add theme node$/i }).click()
const nodes = await page.getByTestId(/theme-node-\d/).all()
return new ThemeNodeImpl(nodes.length, page)
return new ThemeNodeImpl(nodes.length.toString(), page)
}
}

Expand All @@ -44,7 +45,7 @@ export const test = base.extend<{ testRepo: TestRepo }>({

class ThemeNodeImpl implements ThemeNode {
constructor(
private readonly nodeId: number,
private readonly nodeId: string,
private readonly page: Page
) {}

Expand Down Expand Up @@ -84,12 +85,29 @@ class ThemeNodeImpl implements ThemeNode {
})
}

get #attributesInputLocator() {
return this.page
.getByTestId(new RegExp(`^theme-node-${this.nodeId}$`))
.getByRole('textbox', {
name: /attributes/i
async createNode() {
await this.#rootLocator
.getByRole('button', {
name: new RegExp(
`add theme node to ${this.nodeId.replaceAll('.', '\\')}`,
'i'
)
})
.click()
const nodes = await this.#rootLocator
.getByTestId(/theme-node-\d(.\d+)*/)
.all()
return new ThemeNodeImpl(`${this.nodeId}.${nodes.length}`, this.page)
}

get #rootLocator() {
return this.page.getByTestId(new RegExp(`^theme-node-${this.nodeId}$`))
}

get #attributesInputLocator() {
return this.#rootLocator.getByRole('textbox', {
name: /attributes/i
})
}

get #attributes() {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 77 additions & 0 deletions e2e/tests/multipleThemes.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,80 @@ test('if multiple themes enabled on same node, the last one defined in the confi

await expect(page).toHaveScreenshot()
})

test('themes can be overwritten by themes enabled higher in the tree by using class names regardless of theme declaration order', async ({
page,
testRepo
}) => {
const node1 = await testRepo.openWithConfig({
defaultTheme: {
extend: {
colors: {
primary: 'blue'
}
}
},
themes: [
{
name: 'themeOne',
extend: {
colors: {
primary: 'red'
}
}
},
{
name: 'themeTwo',
extend: {
colors: {
primary: 'green'
}
}
}
]
})

await node1.setClass('themeOne')

const node2 = await node1.createNode()

await node2.setClass('themeTwo')

await expect(page).toHaveScreenshot({ fullPage: true })

const node3 = await testRepo.openWithConfig({
defaultTheme: {
extend: {
colors: {
primary: 'blue'
}
}
},
themes: [
{
name: 'themeTwo',
extend: {
colors: {
primary: 'green'
}
}
},
{
name: 'themeOne',
extend: {
colors: {
primary: 'red'
}
}
}
]
})

await node3.setClass('themeOne')

const node4 = await node1.createNode()

await node4.setClass('themeTwo')

await expect(page).toHaveScreenshot({ fullPage: true })
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion e2e/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"module": "esnext"
"module": "esnext",
"target": "esnext"
},
"include": ["."],
"exclude": ["test_repos/templates"]
Expand Down

0 comments on commit cdef1c6

Please sign in to comment.