|
1 | | -import {openURLSafely, renderLinks} from './dev.js' |
2 | | -import {describe, expect, test, vi} from 'vitest' |
| 1 | +import {openURLSafely, renderLinks, createKeypressHandler} from './dev.js' |
| 2 | +import {describe, expect, test, vi, beforeEach, afterEach} from 'vitest' |
3 | 3 | import {buildTheme} from '@shopify/cli-kit/node/themes/factories' |
4 | 4 | import {DEVELOPMENT_THEME_ROLE} from '@shopify/cli-kit/node/themes/utils' |
5 | 5 | import {renderSuccess, renderWarning} from '@shopify/cli-kit/node/ui' |
@@ -102,3 +102,134 @@ describe('openURLSafely', () => { |
102 | 102 | }) |
103 | 103 | }) |
104 | 104 | }) |
| 105 | + |
| 106 | +describe('createKeypressHandler', () => { |
| 107 | + const urls = { |
| 108 | + local: 'http://127.0.0.1:9292', |
| 109 | + giftCard: 'http://127.0.0.1:9292/gift_cards/[store_id]/preview', |
| 110 | + themeEditor: 'https://my-store.myshopify.com/admin/themes/123/editor?hr=9292', |
| 111 | + preview: 'https://my-store.myshopify.com/?preview_theme_id=123', |
| 112 | + } |
| 113 | + |
| 114 | + const ctx = {lastRequestedPath: '/'} |
| 115 | + |
| 116 | + beforeEach(() => { |
| 117 | + vi.mocked(openURL).mockResolvedValue(true) |
| 118 | + vi.useFakeTimers() |
| 119 | + }) |
| 120 | + |
| 121 | + afterEach(() => { |
| 122 | + vi.useRealTimers() |
| 123 | + }) |
| 124 | + |
| 125 | + test('opens localhost when "t" is pressed', () => { |
| 126 | + // Given |
| 127 | + const handler = createKeypressHandler(urls, ctx) |
| 128 | + |
| 129 | + // When |
| 130 | + handler('t', {name: 't'}) |
| 131 | + |
| 132 | + // Then |
| 133 | + expect(openURL).toHaveBeenCalledWith(urls.local) |
| 134 | + }) |
| 135 | + |
| 136 | + test('opens theme preview when "p" is pressed', () => { |
| 137 | + // Given |
| 138 | + const handler = createKeypressHandler(urls, ctx) |
| 139 | + |
| 140 | + // When |
| 141 | + handler('p', {name: 'p'}) |
| 142 | + |
| 143 | + // Then |
| 144 | + expect(openURL).toHaveBeenCalledWith(urls.preview) |
| 145 | + }) |
| 146 | + |
| 147 | + test('opens theme editor when "e" is pressed', () => { |
| 148 | + // Given |
| 149 | + const handler = createKeypressHandler(urls, ctx) |
| 150 | + |
| 151 | + // When |
| 152 | + handler('e', {name: 'e'}) |
| 153 | + |
| 154 | + // Then |
| 155 | + expect(openURL).toHaveBeenCalledWith(urls.themeEditor) |
| 156 | + }) |
| 157 | + |
| 158 | + test('opens gift card preview when "g" is pressed', () => { |
| 159 | + // Given |
| 160 | + const handler = createKeypressHandler(urls, ctx) |
| 161 | + |
| 162 | + // When |
| 163 | + handler('g', {name: 'g'}) |
| 164 | + |
| 165 | + // Then |
| 166 | + expect(openURL).toHaveBeenCalledWith(urls.giftCard) |
| 167 | + }) |
| 168 | + |
| 169 | + test('appends preview path to theme editor URL when lastRequestedPath is not "/"', () => { |
| 170 | + // Given |
| 171 | + const ctxWithPath = {lastRequestedPath: '/products/test-product'} |
| 172 | + const handler = createKeypressHandler(urls, ctxWithPath) |
| 173 | + |
| 174 | + // When |
| 175 | + handler('e', {name: 'e'}) |
| 176 | + |
| 177 | + // Then |
| 178 | + expect(openURL).toHaveBeenCalledWith( |
| 179 | + `${urls.themeEditor}&previewPath=${encodeURIComponent('/products/test-product')}`, |
| 180 | + ) |
| 181 | + }) |
| 182 | + |
| 183 | + test('debounces rapid keypresses - only opens URL once during debounce window', () => { |
| 184 | + // Given |
| 185 | + const handler = createKeypressHandler(urls, ctx) |
| 186 | + |
| 187 | + // When |
| 188 | + handler('t', {name: 't'}) |
| 189 | + handler('t', {name: 't'}) |
| 190 | + handler('t', {name: 't'}) |
| 191 | + handler('t', {name: 't'}) |
| 192 | + |
| 193 | + // Then |
| 194 | + expect(openURL).toHaveBeenCalledTimes(1) |
| 195 | + expect(openURL).toHaveBeenCalledWith(urls.local) |
| 196 | + }) |
| 197 | + |
| 198 | + test('allows keypresses after debounce period expires', () => { |
| 199 | + // Given |
| 200 | + const handler = createKeypressHandler(urls, ctx) |
| 201 | + |
| 202 | + // When |
| 203 | + handler('t', {name: 't'}) |
| 204 | + expect(openURL).toHaveBeenCalledTimes(1) |
| 205 | + |
| 206 | + handler('t', {name: 't'}) |
| 207 | + handler('t', {name: 't'}) |
| 208 | + expect(openURL).toHaveBeenCalledTimes(1) |
| 209 | + |
| 210 | + // Advance time to exceed debounce period |
| 211 | + vi.advanceTimersByTime(100) |
| 212 | + |
| 213 | + handler('p', {name: 'p'}) |
| 214 | + |
| 215 | + // Then |
| 216 | + expect(openURL).toHaveBeenCalledTimes(2) |
| 217 | + expect(openURL).toHaveBeenNthCalledWith(1, urls.local) |
| 218 | + expect(openURL).toHaveBeenNthCalledWith(2, urls.preview) |
| 219 | + }) |
| 220 | + |
| 221 | + test('debounces different keys during the same debounce window', () => { |
| 222 | + // Given |
| 223 | + const handler = createKeypressHandler(urls, ctx) |
| 224 | + |
| 225 | + // When |
| 226 | + handler('t', {name: 't'}) |
| 227 | + handler('p', {name: 'p'}) |
| 228 | + handler('e', {name: 'e'}) |
| 229 | + handler('g', {name: 'g'}) |
| 230 | + |
| 231 | + // Then |
| 232 | + expect(openURL).toHaveBeenCalledTimes(1) |
| 233 | + expect(openURL).toHaveBeenCalledWith(urls.local) |
| 234 | + }) |
| 235 | +}) |
0 commit comments