Skip to content

Commit dff8ab2

Browse files
Merge pull request #106 from RyanClementsHax/playwright
Add more e2e tests
2 parents 2e87d0d + cdef1c6 commit dff8ab2

File tree

64 files changed

+900
-376
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+900
-376
lines changed

README.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ module.exports = {
144144

145145
```html
146146
<!-- this example uses pure html for demonstration purposes -->
147-
<!DOCTYPE html>
147+
<!doctype html>
148148
<html lang="en">
149149
<head>
150150
<!-- ... -->
@@ -162,7 +162,7 @@ You do this by adding a class of the theme's name to whatever you want themed. S
162162

163163
```html
164164
<!-- this example uses pure html for demonstration purposes -->
165-
<!DOCTYPE html>
165+
<!doctype html>
166166
<html lang="en">
167167
<head>
168168
<!-- ... -->
@@ -237,7 +237,7 @@ require('tailwindcss-themer')({
237237
```
238238

239239
```html
240-
<!DOCTYPE html>
240+
<!doctype html>
241241
<html lang="en">
242242
<head>
243243
<!-- ... -->
@@ -250,7 +250,7 @@ require('tailwindcss-themer')({
250250
```
251251

252252
```html
253-
<!DOCTYPE html>
253+
<!doctype html>
254254
<html lang="en">
255255
<head>
256256
<!-- ... -->
@@ -263,7 +263,7 @@ require('tailwindcss-themer')({
263263
```
264264

265265
```html
266-
<!DOCTYPE html>
266+
<!doctype html>
267267
<html lang="en">
268268
<head>
269269
<!-- ... -->
@@ -332,7 +332,7 @@ require('tailwindcss-themer')({
332332
```
333333

334334
```html
335-
<!DOCTYPE html>
335+
<!doctype html>
336336
<html lang="en">
337337
<head>
338338
<!-- ... -->
@@ -345,7 +345,7 @@ require('tailwindcss-themer')({
345345
```
346346

347347
```html
348-
<!DOCTYPE html>
348+
<!doctype html>
349349
<html lang="en">
350350
<head>
351351
<!-- ... -->
@@ -388,10 +388,10 @@ In order to prevent a [flash of unstyled content](https://css-tricks.com/flash-o
388388

389389
### Simultaneous themes
390390

391-
Because this plugin enables themes based on existance of classes, it is possible to have multiple themes enabled at the same time. They can be overlapping or not. Its all up to how you apply the classes!
391+
Because this plugin enables themes in part based on existance of classes, it is possible to have multiple themes enabled at the same time. They can be overlapping or not. Its all up to how you apply the classes!
392392

393393
```html
394-
<!DOCTYPE html>
394+
<!doctype html>
395395
<html lang="en">
396396
<head>
397397
<!-- ... -->
@@ -656,7 +656,7 @@ As specified above, variants are generated for every named theme you make, even
656656
The theme variant generated for the default theme is `defaultTheme` (e.g. `defaultTheme:rounded-sm`), but this now requires that instead of omitting any theme class to enable the default theme, you explicitly declare you are using the default theme by adding the class of `defaultTheme` to the place you want themed (no other feature is affected by this, using the default theme variant is the only feature that requires you to add the `defaultTheme` class to use). This is because I haven't been able to create a css selector that excludes all parents with any of the other theme classes. If you can make one, feel free to [open up an issue](https://github.com/RyanClementsHax/tailwindcss-themer/issues).
657657

658658
```html
659-
<!DOCTYPE html>
659+
<!doctype html>
660660
<html lang="en">
661661
<head>
662662
<!-- ... -->
@@ -670,7 +670,7 @@ The theme variant generated for the default theme is `defaultTheme` (e.g. `defau
670670
```
671671

672672
```html
673-
<!DOCTYPE html>
673+
<!doctype html>
674674
<html lang="en">
675675
<head>
676676
<!-- ... -->
@@ -683,7 +683,7 @@ The theme variant generated for the default theme is `defaultTheme` (e.g. `defau
683683
```
684684

685685
```html
686-
<!DOCTYPE html>
686+
<!doctype html>
687687
<html lang="en">
688688
<head>
689689
<!-- ... -->

e2e/package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"execa": "^8.0.1",
1717
"fs-extra": "^11.1.1",
1818
"get-port": "^7.0.0",
19+
"pidtree": "^0.6.0",
1920
"serialize-javascript": "^6.0.1"
2021
}
2122
}

e2e/playwright.config.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,24 @@ export default defineConfig({
3434

3535
/* Configure projects for major browsers */
3636
projects: [
37+
// Runs before all other projects to initialize all int tests builds without concurrency problems
3738
{
3839
name: 'chromium',
3940
use: { ...devices['Desktop Chrome'] }
4041
},
4142

4243
{
4344
name: 'firefox',
44-
use: { ...devices['Desktop Firefox'] }
45+
use: { ...devices['Desktop Firefox'] },
46+
// Counts on the first project to initialize all int test builds to reuse for a performance boost
47+
dependencies: ['chromium']
4548
},
4649

4750
{
4851
name: 'webkit',
49-
use: { ...devices['Desktop Safari'] }
52+
use: { ...devices['Desktop Safari'] },
53+
// Counts on the first project to initialize all int test builds to reuse for a performance boost
54+
dependencies: ['chromium']
5055
}
5156

5257
/* Test against mobile viewports. */
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import serialize from 'serialize-javascript'
2+
import getPort from 'get-port'
3+
import { MultiThemePluginOptions } from '@/utils/optionsUtils'
4+
import {
5+
ServerStarted,
6+
StartServerResult,
7+
StopServerCallback,
8+
createIsolatedRepoInstance,
9+
parseClasses
10+
} from '.'
11+
import { type Config as TailwindConfig } from 'tailwindcss'
12+
13+
export interface OpenOptions {
14+
instanceId: number
15+
titlePath: string[]
16+
}
17+
18+
export async function openWithConfig(
19+
config: MultiThemePluginOptions,
20+
options: OpenOptions
21+
): Promise<{ url: string; stop: StopServerCallback }> {
22+
const tmpDirName = [
23+
...options.titlePath.map(x => x.replace(/ /g, '_')),
24+
options.instanceId
25+
].join('-')
26+
27+
const { instance, isAlreadyInitialized } = await createIsolatedRepoInstance({
28+
template: 'create-react-app',
29+
tmpDirName
30+
})
31+
32+
const buildDir = instance.getBuildDir()
33+
34+
if (!isAlreadyInitialized) {
35+
const classesToPreventPurging = parseClasses(config)
36+
37+
const tailwindConfig: TailwindConfig = {
38+
content: ['./src/**/*.{js,jsx,ts,tsx}'],
39+
safelist: classesToPreventPurging,
40+
theme: {
41+
extend: {}
42+
}
43+
}
44+
45+
const { filePath: tailwindConfigFilePath } = await instance.writeFile(
46+
'tailwind.config.js',
47+
`module.exports = {
48+
...${JSON.stringify(tailwindConfig)},
49+
plugins: [require('tailwindcss-themer')(${serialize(config)})]
50+
}`
51+
)
52+
53+
await instance.build({
54+
command: ['npm', ['run', 'build']],
55+
env: {
56+
TAILWIND_CONFIG_PATH: tailwindConfigFilePath,
57+
BUILD_PATH: buildDir
58+
}
59+
})
60+
}
61+
62+
const { url, stop } = await startServerWithRetry({
63+
maxAttempts: 2,
64+
async startServer() {
65+
const port = await getPort()
66+
return await instance.startServer({
67+
command: ['npm', ['run', 'serve', '--', buildDir]],
68+
env: {
69+
PORT: port.toFixed(0)
70+
},
71+
isServerStarted: ({ stdout, template }) => {
72+
const startupLogMatch: RegExpMatchArray | null = stdout.match(
73+
/Accepting connections at\s+http:\/\/localhost:(\d+)\s/
74+
)
75+
if (startupLogMatch) {
76+
const parsedPort = parseInt(startupLogMatch[1], 10)
77+
78+
if (port !== parsedPort) {
79+
return {
80+
started: false,
81+
continueWaiting: false,
82+
reason: `Expected ${template} to start on port ${port}, but it started on port ${parsedPort}`
83+
}
84+
}
85+
86+
return { started: true, url: `http://localhost:${port}` }
87+
}
88+
89+
return { started: false, continueWaiting: true }
90+
}
91+
})
92+
}
93+
})
94+
95+
return {
96+
url,
97+
stop
98+
}
99+
}
100+
101+
async function startServerWithRetry({
102+
maxAttempts,
103+
startServer
104+
}: {
105+
maxAttempts: number
106+
startServer: () => Promise<StartServerResult>
107+
}): Promise<ServerStarted> {
108+
let attemptNumber = 0
109+
let failedReason = 'unknown'
110+
while (attemptNumber <= maxAttempts) {
111+
attemptNumber++
112+
if (attemptNumber > 1) {
113+
// eslint-disable-next-line no-console
114+
console.log(
115+
`Retrying (attempt ${attemptNumber}) starting the server because: ${failedReason}`
116+
)
117+
}
118+
119+
const result = await startServer()
120+
121+
if (result.started) {
122+
return result
123+
} else {
124+
failedReason = result.reason
125+
}
126+
}
127+
throw new Error(
128+
`Attempted to start server ${attemptNumber} times but couldn't start the server\n\n${failedReason}`
129+
)
130+
}

0 commit comments

Comments
 (0)