Skip to content

Commit

Permalink
Merge pull request #5198 from Shopify/01-15-don_t_show_dev_shorcuts_u…
Browse files Browse the repository at this point in the history
…ntil_dev_session_is_ready

Don't show dev shortcuts until dev session is ready
  • Loading branch information
isaacroldan authored Jan 16, 2025
2 parents 31ee2c2 + 7b5b5a1 commit 43059d7
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 7 deletions.
6 changes: 6 additions & 0 deletions packages/app/src/cli/services/dev/processes/dev-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ let bundleControllers: AbortController[] = []
// Since the watcher can emit events before the dev session is ready, we need to keep track of the status
let isDevSessionReady = false

export function devSessionStatus() {
return {
isDevSessionReady,
}
}

export async function setupDevSessionProcess({
app,
apiKey,
Expand Down
68 changes: 67 additions & 1 deletion packages/app/src/cli/services/dev/ui/components/Dev.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {calculatePrefixColumnSize, Dev} from './Dev.js'
import {fetchAppPreviewMode} from '../../fetch.js'
import {testDeveloperPlatformClient, testUIExtension} from '../../../../models/app/app.test-data.js'
import {devSessionStatus} from '../../processes/dev-session.js'
import {
getLastFrameAfterUnmount,
render,
Expand All @@ -12,14 +13,15 @@ import {
} from '@shopify/cli-kit/node/testing/ui'
import {AbortController, AbortSignal} from '@shopify/cli-kit/node/abort'
import React from 'react'
import {describe, expect, test, vi} from 'vitest'
import {describe, expect, test, vi, beforeEach} from 'vitest'
import {unstyled} from '@shopify/cli-kit/node/output'
import {openURL} from '@shopify/cli-kit/node/system'
import {Writable} from 'stream'

vi.mock('@shopify/cli-kit/node/system')
vi.mock('../../../context.js')
vi.mock('../../fetch.js')
vi.mock('../../processes/dev-session.js')

const developerPlatformClient = testDeveloperPlatformClient()

Expand All @@ -40,6 +42,10 @@ const developerPreview = {
}

describe('Dev', () => {
beforeEach(() => {
vi.mocked(devSessionStatus).mockReturnValue({isDevSessionReady: true})
})

test('renders a stream of concurrent outputs from sub-processes, shortcuts and a preview url', async () => {
// Given
let backendPromiseResolve: () => void
Expand Down Expand Up @@ -968,6 +974,66 @@ describe('Dev', () => {
// unmount so that polling is cleared after every test
renderInstance.unmount()
})

test('updates UI when devSessionEnabled changes from false to true', async () => {
// Given
vi.mocked(devSessionStatus).mockReturnValue({isDevSessionReady: false})

const renderInstance = render(
<Dev
processes={[]}
abortController={new AbortController()}
previewUrl="https://shopify.com"
graphiqlUrl="https://graphiql.shopify.com"
graphiqlPort={1234}
app={{
...testApp,
canEnablePreviewMode: false,
developerPlatformClient: {
...testDeveloperPlatformClient(),
supportsDevSessions: true,
},
}}
developerPreview={developerPreview}
shopFqdn="mystore.shopify.io"
/>,
)

// Initial state - dev session not ready
expect(unstyled(renderInstance.lastFrame()!).replace(/\d/g, '0')).toMatchInlineSnapshot(`
"
────────────────────────────────────────────────────────────────────────────────────────────────────
› Press q │ quit
Preview URL: https://shopify.com
GraphiQL URL: http://localhost:0000/graphiql
"
`)

// When dev session becomes ready
vi.mocked(devSessionStatus).mockReturnValue({isDevSessionReady: true})

// Wait for the polling interval to update the UI
await waitForContent(renderInstance, 'preview in your browser')

// Then - preview shortcut should be visible
expect(unstyled(renderInstance.lastFrame()!).replace(/\d/g, '0')).toMatchInlineSnapshot(`
"
────────────────────────────────────────────────────────────────────────────────────────────────────
› Press g │ open GraphiQL (Admin API) in your browser
› Press p │ preview in your browser
› Press q │ quit
Preview URL: https://shopify.com
GraphiQL URL: http://localhost:0000/graphiql
"
`)

// unmount so that polling is cleared after every test
renderInstance.unmount()
})
})

describe('calculatePrefixColumnSize', () => {
Expand Down
44 changes: 38 additions & 6 deletions packages/app/src/cli/services/dev/ui/components/Dev.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import metadata from '../../../../metadata.js'
import {DeveloperPlatformClient} from '../../../../utilities/developer-platform-client.js'
import {ExtensionInstance} from '../../../../models/extensions/extension-instance.js'
import {devSessionStatus} from '../../processes/dev-session.js'
import {OutputProcess} from '@shopify/cli-kit/node/output'
import {ConcurrentOutput} from '@shopify/cli-kit/node/ui/components'
import {useAbortSignal} from '@shopify/cli-kit/node/ui/hooks'
Expand Down Expand Up @@ -64,6 +65,7 @@ const Dev: FunctionComponent<DevProps> = ({

const {isRawModeSupported: canUseShortcuts} = useStdin()
const pollingInterval = useRef<NodeJS.Timeout>()
const devSessionPollingInterval = useRef<NodeJS.Timeout>()
const localhostGraphiqlUrl = `http://localhost:${graphiqlPort}/graphiql`
const defaultStatusMessage = `Preview URL: ${previewUrl}${
graphiqlUrl ? `\nGraphiQL URL: ${localhostGraphiqlUrl}` : ''
Expand All @@ -83,11 +85,13 @@ const Dev: FunctionComponent<DevProps> = ({
}, 2000)
}
clearInterval(pollingInterval.current)
clearInterval(devSessionPollingInterval.current)
await app.developerPlatformClient.devSessionDelete({appId: app.id, shopFqdn})
await developerPreview.disable()
})

const [devPreviewEnabled, setDevPreviewEnabled] = useState<boolean>(true)
const [devSessionEnabled, setDevSessionEnabled] = useState<boolean>(devSessionStatus().isDevSessionReady)
const [error, setError] = useState<string | undefined>(undefined)

const errorHandledProcesses = useMemo(() => {
Expand All @@ -106,6 +110,32 @@ const Dev: FunctionComponent<DevProps> = ({
})
}, [processes, abortController])

/*
* Poll Dev Session status
*
* Polling mechanism to check if the dev session is ready.
* When the session is ready, the polling stops and the shortcuts are shown.
* Reason is that shortcuts won't work properly until the session is ready and the app is installed.
*
* This only applies for App Management dev-sessions.
*/
useEffect(() => {
const pollDevSession = async () => {
const {isDevSessionReady} = devSessionStatus()
setDevSessionEnabled(isDevSessionReady)
if (isDevSessionReady) clearInterval(devSessionPollingInterval.current)
}

if (app.developerPlatformClient.supportsDevSessions) {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
devSessionPollingInterval.current = setInterval(pollDevSession, 200)
} else {
setDevSessionEnabled(true)
}

return () => clearInterval(devSessionPollingInterval.current)
}, [devSessionStatus])

useEffect(() => {
const pollDevPreviewMode = async () => {
try {
Expand Down Expand Up @@ -160,12 +190,12 @@ const Dev: FunctionComponent<DevProps> = ({
try {
setError('')

if (input === 'p' && previewUrl) {
if (input === 'p' && previewUrl && devSessionEnabled) {
await metadata.addPublicMetadata(() => ({
cmd_dev_preview_url_opened: true,
}))
await openURL(previewUrl)
} else if (input === 'g' && graphiqlUrl) {
} else if (input === 'g' && graphiqlUrl && devSessionEnabled) {
await metadata.addPublicMetadata(() => ({
cmd_dev_graphiql_opened: true,
}))
Expand Down Expand Up @@ -244,15 +274,17 @@ const Dev: FunctionComponent<DevProps> = ({
{devPreviewEnabled ? <Text color="green">✔ on</Text> : <Text color="red">✖ off</Text>}
</Text>
) : null}
{graphiqlUrl ? (
{graphiqlUrl && devSessionEnabled ? (
<Text>
{figures.pointerSmall} Press <Text bold>g</Text> {figures.lineVertical} open GraphiQL (Admin API) in
your browser
</Text>
) : null}
<Text>
{figures.pointerSmall} Press <Text bold>p</Text> {figures.lineVertical} preview in your browser
</Text>
{devSessionEnabled ? (
<Text>
{figures.pointerSmall} Press <Text bold>p</Text> {figures.lineVertical} preview in your browser
</Text>
) : null}
<Text>
{figures.pointerSmall} Press <Text bold>q</Text> {figures.lineVertical} quit
</Text>
Expand Down

0 comments on commit 43059d7

Please sign in to comment.