Skip to content

Commit 7bb8bbe

Browse files
committed
feat(graphiql): add graphiql-console package foundation
Establishes the new React 18 package with complete build infrastructure. Creates a minimal working application with full build/test setup. - Add package.json with dependencies - Configure NX build with explicit inputs for cache invalidation - Add Vite bundler configuration - Add TypeScript configuration - Add basic App component and tests - Add to vitest workspace for test integration All CI checks pass: build, test, lint, type-check
1 parent 70fd1c3 commit 7bb8bbe

File tree

16 files changed

+2033
-39
lines changed

16 files changed

+2033
-39
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/x-icon" href="/src/assets/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>GraphiQL Console</title>
8+
<style>
9+
body {
10+
height: 100%;
11+
margin: 0;
12+
width: 100%;
13+
overflow: hidden;
14+
}
15+
.Polaris-Page--fullWidth {
16+
width: 100%;
17+
}
18+
</style>
19+
</head>
20+
<body>
21+
<div id="root"></div>
22+
<script type="module" src="/src/main.tsx"></script>
23+
</body>
24+
</html>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"name": "@shopify/graphiql-console",
3+
"version": "3.86.0",
4+
"packageManager": "pnpm@10.11.1",
5+
"private": true,
6+
"scripts": {
7+
"build": "nx build",
8+
"clean": "nx clean",
9+
"dev": "nx dev",
10+
"lint": "nx lint",
11+
"lint:fix": "nx lint:fix",
12+
"vitest": "vitest"
13+
},
14+
"dependencies": {
15+
"@graphiql/toolkit": "^0.11.3",
16+
"@shopify/polaris": "^12.27.0",
17+
"@shopify/polaris-icons": "^9.0.0",
18+
"graphiql": "^5.2.0",
19+
"graphql": "^16.10.0",
20+
"monaco-editor": "^0.52.0",
21+
"monaco-graphql": "^1.7.2",
22+
"react": "^18.2.0",
23+
"react-dom": "^18.2.0"
24+
},
25+
"devDependencies": {
26+
"@shopify/react-testing": "^3.0.0",
27+
"@testing-library/react": "^16.3.0",
28+
"@types/react": "^18.2.0",
29+
"@types/react-dom": "^18.2.0",
30+
"@vitejs/plugin-react": "^4.0.0",
31+
"jsdom": "^20.0.3",
32+
"sass": "^1.83.1",
33+
"vite": "6.3.6",
34+
"vite-plugin-monaco-editor": "^1.1.0"
35+
},
36+
"eslintConfig": {
37+
"rules": {
38+
"no-restricted-imports": [
39+
"error",
40+
{
41+
"name": "monaco-editor",
42+
"message": "Use 'monaco-graphql/esm/monaco-editor' instead to avoid bundling 83 languages"
43+
}
44+
]
45+
}
46+
}
47+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"name": "graphiql-console",
3+
"$schema": "../../node_modules/nx/schemas/project-schema.json",
4+
"sourceRoot": "packages/graphiql-console/src",
5+
"projectType": "library",
6+
"tags": ["scope:feature", "scope:graphiql"],
7+
"targets": {
8+
"clean": {
9+
"executor": "nx:run-commands",
10+
"options": {
11+
"command": "pnpm rimraf dist/ ../app/assets/graphiql",
12+
"cwd": "packages/graphiql-console"
13+
}
14+
},
15+
"build": {
16+
"inputs": [
17+
"{projectRoot}/src/**/*",
18+
"{projectRoot}/index.html",
19+
"{projectRoot}/package.json",
20+
"{projectRoot}/vite.config.ts",
21+
"{projectRoot}/tsconfig.json"
22+
],
23+
"outputs": ["{workspaceRoot}/packages/app/assets/graphiql"],
24+
"executor": "nx:run-commands",
25+
"options": {
26+
"command": "pnpm vite build",
27+
"cwd": "packages/graphiql-console"
28+
}
29+
},
30+
"lint": {
31+
"executor": "nx:run-commands",
32+
"options": {
33+
"command": "pnpm eslint src tests",
34+
"cwd": "packages/graphiql-console"
35+
}
36+
},
37+
"lint:fix": {
38+
"executor": "nx:run-commands",
39+
"options": {
40+
"command": "pnpm eslint src tests --fix",
41+
"cwd": "packages/graphiql-console"
42+
}
43+
},
44+
"dev": {
45+
"executor": "nx:run-commands",
46+
"options": {
47+
"command": "pnpm vite dev",
48+
"cwd": "packages/graphiql-console"
49+
}
50+
}
51+
}
52+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import App from './App.tsx'
2+
import React from 'react'
3+
import {render, screen} from '@testing-library/react'
4+
import {describe, test, expect, vi} from 'vitest'
5+
6+
// Mock GraphiQLSection component
7+
vi.mock('./sections/GraphiQL/index.ts', () => ({
8+
GraphiQLSection: () => <div data-testid="graphiql-section">GraphiQLSection</div>,
9+
}))
10+
11+
describe('<App />', () => {
12+
test('renders AppProvider with GraphiQLSection', () => {
13+
render(<App />)
14+
15+
expect(screen.getByTestId('graphiql-section')).toBeDefined()
16+
})
17+
18+
test('provides i18n context to children', () => {
19+
const {container} = render(<App />)
20+
21+
// AppProvider should be rendered (it creates a div wrapper)
22+
expect(container.querySelector('div')).toBeDefined()
23+
})
24+
})
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react'
2+
3+
import {AppProvider} from '@shopify/polaris'
4+
import '@shopify/polaris/build/esm/styles.css'
5+
6+
function App() {
7+
return (
8+
<AppProvider i18n={{}}>
9+
<div>GraphiQL Console</div>
10+
</AppProvider>
11+
)
12+
}
13+
14+
export default App
11.7 KB
Binary file not shown.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {describe, test, expect, vi, beforeEach, afterEach} from 'vitest'
2+
3+
// Mock dependencies
4+
vi.mock('react-dom/client', () => {
5+
const mockRender = vi.fn()
6+
const mockCreateRoot = vi.fn(() => ({
7+
render: mockRender,
8+
}))
9+
return {
10+
createRoot: mockCreateRoot,
11+
}
12+
})
13+
14+
vi.mock('./App.tsx', () => ({
15+
default: () => null,
16+
}))
17+
18+
describe('main.tsx', () => {
19+
let originalGetElementById: typeof document.getElementById
20+
21+
beforeEach(() => {
22+
// Save original method
23+
originalGetElementById = document.getElementById
24+
25+
// Clear module cache to ensure fresh import
26+
vi.resetModules()
27+
})
28+
29+
afterEach(() => {
30+
// Restore original method
31+
document.getElementById = originalGetElementById
32+
})
33+
34+
test('finds root element and renders App', async () => {
35+
const mockRootElement = document.createElement('div')
36+
mockRootElement.id = 'root'
37+
38+
document.getElementById = vi.fn().mockReturnValue(mockRootElement)
39+
40+
// Import main to execute it
41+
const {createRoot} = await import('react-dom/client')
42+
43+
// Dynamic import to trigger execution
44+
await import('./main.tsx')
45+
46+
expect(document.getElementById).toHaveBeenCalledWith('root')
47+
expect(createRoot).toHaveBeenCalledWith(mockRootElement)
48+
})
49+
50+
test('throws error when root element not found', async () => {
51+
document.getElementById = vi.fn().mockReturnValue(null)
52+
53+
// Expect the import to throw
54+
await expect(async () => {
55+
await import('./main.tsx')
56+
}).rejects.toThrow('Root element not found')
57+
})
58+
})
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import App from './App.tsx'
2+
import React from 'react'
3+
import {createRoot} from 'react-dom/client'
4+
5+
const container = document.getElementById('root')
6+
if (!container) {
7+
throw new Error('Root element not found')
8+
}
9+
10+
const root = createRoot(container)
11+
root.render(
12+
<React.StrictMode>
13+
<App />
14+
</React.StrictMode>,
15+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// CSS Modules - named exports pattern
2+
declare module '*.module.scss' {
3+
const classes: {[key: string]: string}
4+
export = classes
5+
}
6+
7+
declare module '*.scss' {
8+
const content: string
9+
export default content
10+
}
11+
12+
declare module '*.module.css' {
13+
const classes: {[key: string]: string}
14+
export = classes
15+
}
16+
17+
// Vite worker imports
18+
declare module '*?worker' {
19+
const workerConstructor: new () => Worker
20+
export default workerConstructor
21+
}
22+
23+
// Vite environment variables
24+
interface ImportMetaEnv {
25+
readonly VITE_GRAPHIQL_BASE_URL?: string
26+
}
27+
28+
interface ImportMeta {
29+
readonly env: ImportMetaEnv
30+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import '@shopify/react-testing/matchers'
2+
3+
Object.defineProperty(window, 'matchMedia', {
4+
writable: true,
5+
value: vi.fn().mockImplementation((query) => ({
6+
matches: false,
7+
media: query,
8+
onchange: null,
9+
addEventListener: vi.fn(),
10+
removeEventListener: vi.fn(),
11+
dispatchEvent: vi.fn(),
12+
addListener: vi.fn(),
13+
removeListener: vi.fn(),
14+
})),
15+
})

0 commit comments

Comments
 (0)