Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"rimraf": "^6.1.3",
"ts-node": "^10.9.1",
"typescript": "5.9.3",
"vitest": "^3.1.4",
"vitest": "^4.1.0",
"zod": "3.25.76"
},
"workspaces": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {stageFile} from './stage-file.js'
import {adminRequestDoc} from '@shopify/cli-kit/node/api/admin'
import {fetch} from '@shopify/cli-kit/node/http'
import {renderSingleTask, RenderSingleTaskOptions} from '@shopify/cli-kit/node/ui'
import {describe, test, expect, vi, beforeEach} from 'vitest'

vi.mock('@shopify/cli-kit/node/api/admin')
vi.mock('@shopify/cli-kit/node/session')
vi.mock('@shopify/cli-kit/node/http')
vi.mock('@shopify/cli-kit/node/ui')

describe('stageFile', () => {
const mockSession = {token: 'test-token', storeFqdn: 'test-store.myshopify.com'}
Expand All @@ -30,7 +32,14 @@ describe('stageFile', () => {

let formDataAppendSpy: ReturnType<typeof vi.spyOn>

function fileAppendCall() {
return formDataAppendSpy.mock.calls.find((call: unknown[]) => call[0] === 'file')
}

beforeEach(() => {
vi.mocked(renderSingleTask).mockImplementation(async (options: RenderSingleTaskOptions<unknown>) => {
return options.task(vi.fn())
})
vi.mocked(fetch).mockResolvedValue({
ok: true,
text: vi.fn().mockResolvedValue(''),
Expand Down Expand Up @@ -59,8 +68,7 @@ describe('stageFile', () => {
variablesJsonl,
})

const fileAppendCall = formDataAppendSpy.mock.calls.find((call) => call[0] === 'file')
const uploadedBlob = fileAppendCall?.[1] as Blob
const uploadedBlob = fileAppendCall()?.[1] as Blob
const uploadedContent = await uploadedBlob?.text()

expect(uploadedContent).toBe('{"input":{"id":"gid://shopify/Product/123","tags":["test"]}}')
Expand All @@ -80,8 +88,7 @@ describe('stageFile', () => {
variablesJsonl,
})

const fileAppendCall = formDataAppendSpy.mock.calls.find((call) => call[0] === 'file')
const uploadedBlob = fileAppendCall?.[1] as Blob
const uploadedBlob = fileAppendCall()?.[1] as Blob
const uploadedContent = await uploadedBlob?.text()

const expectedContent = [
Expand Down
11 changes: 5 additions & 6 deletions packages/app/src/cli/services/dev/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,11 @@ describe('devUIExtensions()', () => {

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
vi.spyOn(store, 'ExtensionsPayloadStore').mockImplementation(
() =>
({
mock: 'payload-store',
}) as unknown as store.ExtensionsPayloadStore,
)
vi.spyOn(store, 'ExtensionsPayloadStore').mockImplementation(function () {
return {
mock: 'payload-store',
} as unknown as store.ExtensionsPayloadStore
} as any)
vi.spyOn(server, 'setupHTTPServer').mockReturnValue({
mock: 'http-server',
close: serverCloseSpy,
Expand Down
13 changes: 9 additions & 4 deletions packages/app/src/cli/services/dev/extension/websocket.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ vi.mock('./websocket/handlers.js')
vi.mock('ws')

describe('setupWebsocketConnection', () => {
const websocketServer = new WebSocketServer()
const websocketServer = {
close: vi.fn(),
clients: new Set(),
} as unknown as WebSocketServer
const handler: any = {}
const payloadStore: ExtensionsPayloadStore = {on: vi.fn()} as any
const httpServer: Server = {on: vi.fn()} as any
Expand All @@ -19,7 +22,9 @@ describe('setupWebsocketConnection', () => {

beforeEach(() => {
vi.useFakeTimers()
vi.mocked(WebSocketServer).mockReturnValue(websocketServer)
vi.mocked(WebSocketServer).mockImplementation(function () {
return websocketServer
} as any)
})

afterEach(() => {
Expand Down Expand Up @@ -63,7 +68,7 @@ describe('setupWebsocketConnection', () => {
test('pings alive clients periodically to keep the connection alive', () => {
// Given
const client = {readyState: 1, ping: vi.fn()}
WebSocketServer.prototype.clients = [client] as any
websocketServer.clients = new Set([client]) as any
vi.mocked(getPayloadUpdateHandler).mockReturnValue(handler)

// When
Expand All @@ -77,7 +82,7 @@ describe('setupWebsocketConnection', () => {
test("doesn't ping disconnected clients periodically", () => {
// Given
const client = {readyState: 3, ping: vi.fn()}
WebSocketServer.prototype.clients = [client] as any
websocketServer.clients = new Set([client]) as any
vi.mocked(getPayloadUpdateHandler).mockReturnValue(handler)

// When
Expand Down
15 changes: 13 additions & 2 deletions packages/app/src/cli/services/dev/select-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ import {
} from '../../prompts/dev.js'
import {testDeveloperPlatformClient} from '../../models/app/app.test-data.js'
import {ClientName} from '../../utilities/developer-platform-client.js'
import {sleep} from '@shopify/cli-kit/node/system'
import {renderTasks, Task} from '@shopify/cli-kit/node/ui'
import {describe, expect, vi, test} from 'vitest'

vi.mock('../../prompts/dev')
vi.mock('./fetch')
vi.mock('@shopify/cli-kit/node/context/local')
vi.mock('@shopify/cli-kit/node/system')
vi.mock('@shopify/cli-kit/node/ui')

const ORG1: Organization = {
id: '1',
Expand Down Expand Up @@ -178,10 +181,18 @@ describe('selectStore', async () => {

test('prompts user to create & reload, fetches 10 times and tries again if reload is true', async () => {
// Given
vi.mocked(sleep).mockResolvedValue()
vi.mocked(renderTasks).mockImplementation(async (tasks: Task[]) => {
for (const task of tasks) {
// eslint-disable-next-line no-await-in-loop
await task.task({}, task)
}
return {}
})
vi.mocked(selectStorePrompt).mockResolvedValue(undefined)
vi.mocked(reloadStoreListPrompt).mockResolvedValueOnce(true)
vi.mocked(reloadStoreListPrompt).mockResolvedValueOnce(false)
vi.mocked(reloadStoreListPrompt).mockResolvedValueOnce(true).mockResolvedValueOnce(false)
const developerPlatformClient = testDeveloperPlatformClient({clientName: ClientName.Partners})
vi.mocked(developerPlatformClient.devStoresForOrg).mockResolvedValue({stores: [], hasMorePages: false})

// When
const got = selectStore({stores: [], hasMorePages: false}, ORG1, developerPlatformClient)
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/cli/utilities/mkcert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ describe('mkcert', () => {
await setup(tempDir)

const mockFetch = vi.fn().mockResolvedValue({
ok: true,
ok: false,
text: async () => 'LICENSE CONTENT',
} as unknown as Response)
const mockOutput = mockAndCaptureOutput()
Expand Down
5 changes: 4 additions & 1 deletion packages/cli-kit/src/private/node/ui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ export function renderOnce(element: JSX.Element, {logLevel = 'info', renderOptio
}

export async function render(element: JSX.Element, options?: RenderOptions) {
const {waitUntilExit} = inkRender(<InkLifecycleRoot>{element}</InkLifecycleRoot>, options)
const {waitUntilExit} = inkRender(<InkLifecycleRoot>{element}</InkLifecycleRoot>, {
patchConsole: !isUnitTest(),
...options,
})
await waitUntilExit()
}

Expand Down
13 changes: 13 additions & 0 deletions packages/cli-kit/src/public/node/base-command.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,13 @@ describe('applying environments', async () => {
})
}

async function waitForInfoOutput(outputMock: ReturnType<typeof mockAndCaptureOutput>) {
await vi.waitFor(() => {
expect(outputMock.info()).toEqual(expect.anything())
expect(outputMock.info()).not.toEqual('')
})
}

runTestInTmpDir(
'does not apply a environment when none is specified and there is no default',
async (tmpDir: string) => {
Expand Down Expand Up @@ -234,6 +241,7 @@ describe('applying environments', async () => {

// Then
expectFlags(tmpDir, 'validEnvironment')
await waitForInfoOutput(outputMock)
expect(outputMock.info()).toMatchInlineSnapshot(`
"╭─ info ───────────────────────────────────────────────────────────────────────╮
│ │
Expand All @@ -257,6 +265,7 @@ describe('applying environments', async () => {

// Then
expectFlags(tmpDir, 'default')
await waitForInfoOutput(outputMock)
expect(outputMock.info()).toMatchInlineSnapshot(`
"╭─ info ───────────────────────────────────────────────────────────────────────╮
│ │
Expand Down Expand Up @@ -333,6 +342,7 @@ describe('applying environments', async () => {

// Then
expect(testResult.someString).toEqual('cheesy')
await waitForInfoOutput(outputMock)
expect(outputMock.info()).toMatchInlineSnapshot(`
"╭─ info ───────────────────────────────────────────────────────────────────────╮
│ │
Expand Down Expand Up @@ -449,6 +459,7 @@ describe('applying environments', async () => {

// Then
expectFlags(tmpDir, 'environmentWithDefaultOverride')
await waitForInfoOutput(outputMock)
expect(outputMock.info()).toMatchInlineSnapshot(`
"╭─ info ───────────────────────────────────────────────────────────────────────╮
│ │
Expand All @@ -471,6 +482,7 @@ describe('applying environments', async () => {

// Then
expectFlags(tmpDir, 'environmentMatchingDefault')
await waitForInfoOutput(outputMock)
expect(outputMock.info()).toMatchInlineSnapshot(`
"╭─ info ───────────────────────────────────────────────────────────────────────╮
│ │
Expand All @@ -493,6 +505,7 @@ describe('applying environments', async () => {

// Then
expectFlags(tmpDir, 'environmentWithPassword')
await waitForInfoOutput(outputMock)
expect(outputMock.info()).toMatchInlineSnapshot(`
"╭─ info ───────────────────────────────────────────────────────────────────────╮
│ │
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import {SerialBatchProcessor} from './serial-batch-processor.js'
import {describe, test, expect, vi, beforeEach} from 'vitest'
import type {Mock} from 'vitest'

describe('SerialBatchProcessor', () => {
let processBatchMock: ReturnType<typeof vi.fn>
let processBatchMock: Mock<(items: string[]) => Promise<void>>

beforeEach(() => {
// Default mock that resolves immediately
processBatchMock = vi.fn(async (_items: string[]) => Promise.resolve())
processBatchMock = vi.fn<(items: string[]) => Promise<void>>(async () => {})
})

test('should process a single item in a batch', async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli-kit/src/public/node/themes/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {AbortError} from '../error.js'
import {test, vi, expect, describe, beforeEach} from 'vitest'
import {ClientError} from 'graphql-request'

vi.mock('@shopify/cli-kit/node/api/admin')
vi.mock('../api/admin.js')
vi.mock('@shopify/cli-kit/node/system')
vi.stubGlobal('fetch', vi.fn())

Expand Down
Loading
Loading