|
| 1 | +import { mouseClickAtPoint } from '../../components/canvas/event-helpers.test-utils' |
| 2 | +import type { EditorRenderResult } from '../../components/canvas/ui-jsx.test-utils' |
1 | 3 | import { renderTestEditorWithModel } from '../../components/canvas/ui-jsx.test-utils'
|
| 4 | +import { switchEditorMode } from '../../components/editor/actions/action-creators' |
| 5 | +import { EditorModes } from '../../components/editor/editor-modes' |
| 6 | +import { StoryboardFilePath } from '../../components/editor/store/editor-state' |
| 7 | +import { createModifiedProject } from '../../sample-projects/sample-project-utils.test-utils' |
2 | 8 | import { setFeatureForBrowserTestsUseInDescribeBlockOnly } from '../../utils/utils.test-utils'
|
| 9 | +import { windowPoint } from '../shared/math-utils' |
| 10 | +import { TailwindConfigPath } from './tailwind-config' |
3 | 11 | import { Project } from './tailwind.test-utils'
|
4 | 12 |
|
5 | 13 | describe('rendering tailwind projects in the editor', () => {
|
@@ -133,4 +141,166 @@ describe('rendering tailwind projects in the editor', () => {
|
133 | 141 | })
|
134 | 142 | }
|
135 | 143 | })
|
| 144 | + |
| 145 | + describe('Remix', () => { |
| 146 | + const projectWithMultipleRoutes = createModifiedProject({ |
| 147 | + [StoryboardFilePath]: `import * as React from 'react' |
| 148 | + import { RemixScene, Storyboard } from 'utopia-api' |
| 149 | + |
| 150 | + export var storyboard = ( |
| 151 | + <Storyboard data-uid='storyboard'> |
| 152 | + <RemixScene |
| 153 | + className='absolute top-[100px] left-[200px] w-[700px] h-[700px]' |
| 154 | + data-label='Playground' |
| 155 | + data-uid='remix' |
| 156 | + /> |
| 157 | + </Storyboard> |
| 158 | + ) |
| 159 | + `, |
| 160 | + ['/app/root.js']: `import React from 'react' |
| 161 | + import { Outlet } from '@remix-run/react' |
| 162 | + |
| 163 | + export default function Root() { |
| 164 | + return ( |
| 165 | + <div data-testid='root' className='flex flex-col gap-10 bg-red-200 text-2xl'> |
| 166 | + I am Root! |
| 167 | + <Outlet /> |
| 168 | + </div> |
| 169 | + ) |
| 170 | + } |
| 171 | + `, |
| 172 | + ['/app/routes/_index.js']: `import React from 'react' |
| 173 | + import { Link } from '@remix-run/react' |
| 174 | + |
| 175 | + export default function Index() { |
| 176 | + return ( |
| 177 | + <div data-testid='index' className='flex flex-col gap-8'> |
| 178 | + Index page |
| 179 | + <Link to='/about' data-testid='remix-link'>About</Link> |
| 180 | + </div> |
| 181 | + ) |
| 182 | + } |
| 183 | + `, |
| 184 | + ['/app/routes/about.js']: `import React from 'react' |
| 185 | + |
| 186 | + export default function About() { |
| 187 | + return ( |
| 188 | + <div data-testid='about' className='flex flex-row gap-6 p-4'> |
| 189 | + <span data-testid='about-text' className='text-shadow-md'>About page</span> |
| 190 | + </div> |
| 191 | + ) |
| 192 | + } |
| 193 | + `, |
| 194 | + '/src/app.css': ` |
| 195 | + @tailwind base; |
| 196 | + @tailwind components; |
| 197 | + @tailwind utilities; |
| 198 | + `, |
| 199 | + [TailwindConfigPath]: ` |
| 200 | + const Tailwind = { |
| 201 | + theme: { |
| 202 | + colors: { |
| 203 | + transparent: 'transparent', |
| 204 | + current: 'currentColor', |
| 205 | + white: '#ffffff', |
| 206 | + purple: '#3f3cbb', |
| 207 | + midnight: '#121063', |
| 208 | + metal: '#565584', |
| 209 | + tahiti: '#3ab7bf', |
| 210 | + silver: '#ecebff', |
| 211 | + 'bubble-gum': '#ff77e9', |
| 212 | + bermuda: '#78dcca', |
| 213 | + }, |
| 214 | + }, |
| 215 | + plugins: [ |
| 216 | + function ({ addUtilities }) { |
| 217 | + const newUtilities = { |
| 218 | + '.text-shadow': { |
| 219 | + textShadow: '2px 2px 4px rgba(0, 0, 0, 0.1)', |
| 220 | + }, |
| 221 | + '.text-shadow-md': { |
| 222 | + textShadow: '3px 3px 6px rgba(0, 0, 0, 0.2)', |
| 223 | + }, |
| 224 | + '.text-shadow-lg': { |
| 225 | + textShadow: '4px 4px 8px rgba(0, 0, 0, 0.3)', |
| 226 | + }, |
| 227 | + '.text-shadow-none': { |
| 228 | + textShadow: 'none', |
| 229 | + }, |
| 230 | + } |
| 231 | + |
| 232 | + addUtilities(newUtilities, ['responsive', 'hover']) |
| 233 | + }, |
| 234 | + ], |
| 235 | + } |
| 236 | + export default Tailwind`, |
| 237 | + }) |
| 238 | + |
| 239 | + it('can render content in a RemixScene', async () => { |
| 240 | + const editor = await renderTestEditorWithModel( |
| 241 | + projectWithMultipleRoutes, |
| 242 | + 'await-first-dom-report', |
| 243 | + ) |
| 244 | + { |
| 245 | + const root = editor.renderedDOM.getByTestId('root') |
| 246 | + const { backgroundColor, display, flexDirection, gap, fontSize } = getComputedStyle(root) |
| 247 | + expect({ backgroundColor, display, flexDirection, gap, fontSize }).toEqual({ |
| 248 | + backgroundColor: 'rgba(0, 0, 0, 0)', |
| 249 | + display: 'flex', |
| 250 | + flexDirection: 'column', |
| 251 | + fontSize: '24px', |
| 252 | + gap: '40px', |
| 253 | + }) |
| 254 | + } |
| 255 | + { |
| 256 | + const index = editor.renderedDOM.getByTestId('index') |
| 257 | + const { display, flexDirection, gap } = getComputedStyle(index) |
| 258 | + expect({ display, flexDirection, gap }).toEqual({ |
| 259 | + display: 'flex', |
| 260 | + flexDirection: 'column', |
| 261 | + gap: '32px', |
| 262 | + }) |
| 263 | + } |
| 264 | + }) |
| 265 | + it('can render content after navigating to a different page', async () => { |
| 266 | + const editor = await renderTestEditorWithModel( |
| 267 | + projectWithMultipleRoutes, |
| 268 | + 'await-first-dom-report', |
| 269 | + ) |
| 270 | + await switchToLiveMode(editor) |
| 271 | + await clickRemixLink(editor) |
| 272 | + |
| 273 | + { |
| 274 | + const about = editor.renderedDOM.getByTestId('about') |
| 275 | + const { display, flexDirection, gap, padding } = getComputedStyle(about) |
| 276 | + expect({ display, flexDirection, gap, padding }).toEqual({ |
| 277 | + display: 'flex', |
| 278 | + flexDirection: 'row', |
| 279 | + gap: '24px', |
| 280 | + padding: '16px', |
| 281 | + }) |
| 282 | + } |
| 283 | + { |
| 284 | + const aboutText = editor.renderedDOM.getByTestId('about-text') |
| 285 | + const { textShadow } = getComputedStyle(aboutText) |
| 286 | + expect(textShadow).toEqual('rgba(0, 0, 0, 0.2) 3px 3px 6px') |
| 287 | + } |
| 288 | + }) |
| 289 | + }) |
136 | 290 | })
|
| 291 | + |
| 292 | +const switchToLiveMode = (editor: EditorRenderResult) => |
| 293 | + editor.dispatch([switchEditorMode(EditorModes.liveMode())], true) |
| 294 | + |
| 295 | +async function clickLinkWithTestId(editor: EditorRenderResult, testId: string) { |
| 296 | + const targetElement = editor.renderedDOM.queryAllByTestId(testId)[0] |
| 297 | + const targetElementBounds = targetElement.getBoundingClientRect() |
| 298 | + |
| 299 | + const clickPoint = windowPoint({ x: targetElementBounds.x + 5, y: targetElementBounds.y + 5 }) |
| 300 | + await mouseClickAtPoint(targetElement, clickPoint) |
| 301 | +} |
| 302 | + |
| 303 | +async function clickRemixLink(editor: EditorRenderResult) { |
| 304 | + await clickLinkWithTestId(editor, 'remix-link') |
| 305 | + await editor.getDispatchFollowUpActionsFinished() |
| 306 | +} |
0 commit comments