@i18n-micro/core 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,347 +0,0 @@
1
- import type {
2
- RouteLocationAsPathGeneric,
3
- RouteLocationNamedRaw,
4
- RouteLocationNormalizedLoaded,
5
- RouteLocationRaw,
6
- RouteLocationResolvedGeneric,
7
- Router,
8
- } from 'vue-router'
9
- import type { ModuleOptionsExtend } from '@i18n-micro/types'
10
- import { RouteService } from '../src'
11
-
12
- describe('RouteService', () => {
13
- let routeService: RouteService
14
- let mockRouter: jest.Mocked<Router>
15
- let mockI18nConfig: ModuleOptionsExtend
16
- let navigateToMock: jest.Mock
17
-
18
- beforeEach(() => {
19
- // Mock Router
20
- mockRouter = {
21
- currentRoute: { value: { params: { locale: 'en' } } },
22
- resolve: jest.fn((to: RouteLocationRaw | string) => ({
23
- fullPath: typeof to === 'string' ? to : to.path || '',
24
- path: typeof to === 'string' ? to : to.path || '',
25
- query: {},
26
- hash: '',
27
- params: {},
28
- })) as unknown as jest.MockedFunction<Router['resolve']>,
29
- hasRoute: jest.fn((_name: string) => false) as jest.MockedFunction<Router['hasRoute']>,
30
- push: jest.fn(() => Promise.resolve()) as unknown as jest.MockedFunction<Router['push']>,
31
- } as unknown as jest.Mocked<Router>
32
-
33
- // Mock ModuleOptionsExtend
34
- mockI18nConfig = {
35
- apiBaseUrl: '',
36
- dateBuild: 0,
37
- disablePageLocales: false,
38
- isSSG: false,
39
- defaultLocale: 'en',
40
- strategy: 'prefix_except_default',
41
- locales: [
42
- { code: 'en', iso: 'en-US' },
43
- { code: 'de', iso: 'de-DE' },
44
- { code: 'ru', iso: 'ru-RU' },
45
- ],
46
- hashMode: false,
47
- }
48
-
49
- navigateToMock = jest.fn()
50
-
51
- // Initialize RouteService (no setCookie - plugin handles cookies)
52
- routeService = new RouteService(
53
- mockI18nConfig,
54
- mockRouter,
55
- null,
56
- null,
57
- navigateToMock,
58
- )
59
- })
60
-
61
- test('getCurrentLocale should return the correct locale', () => {
62
- const locale = routeService.getCurrentLocale()
63
- expect(locale).toBe('en')
64
- })
65
-
66
- test('getCurrentLocale should return the hash locale if hashMode is enabled', () => {
67
- const mockI18nConfigWithHashMode = { ...mockI18nConfig, hashMode: true }
68
- routeService = new RouteService(mockI18nConfigWithHashMode, mockRouter, 'de', null, navigateToMock)
69
- const locale = routeService.getCurrentLocale()
70
- expect(locale).toBe('de')
71
- })
72
-
73
- test('getCurrentLocale should return the noPrefix locale if noPrefix strategy is enabled', () => {
74
- const mockI18nConfigWithNoPrefix: ModuleOptionsExtend = { ...mockI18nConfig, strategy: 'no_prefix' }
75
- routeService = new RouteService(mockI18nConfigWithNoPrefix, mockRouter, null, 'ru', navigateToMock)
76
- const locale = routeService.getCurrentLocale()
77
- expect(locale).toBe('ru')
78
- })
79
-
80
- test('getCurrentName should return the display name of the current locale', () => {
81
- const mockI18nConfigWithDisplayName = {
82
- ...mockI18nConfig,
83
- locales: [
84
- { code: 'en', iso: 'en-US', displayName: 'English' },
85
- { code: 'de', iso: 'de-DE', displayName: 'German' },
86
- { code: 'ru', iso: 'ru-RU', displayName: 'Russian' },
87
- ],
88
- }
89
- routeService = new RouteService(mockI18nConfigWithDisplayName, mockRouter, null, null, navigateToMock)
90
- const route = { name: 'localized-about-en' } as RouteLocationNormalizedLoaded
91
- const displayName = routeService.getCurrentName(route)
92
- expect(displayName).toBe('English')
93
- })
94
-
95
- test('getRouteName should return the correct route name without locale suffix', () => {
96
- const route = { name: 'localized-about-en' } as RouteLocationNamedRaw
97
- const routeName = routeService.getRouteName(route, 'en')
98
- expect(routeName).toBe('about')
99
- })
100
-
101
- test('switchLocaleRoute should return the correct route for the new locale', () => {
102
- const route = { name: 'localized-about-en', params: {} } as RouteLocationNamedRaw
103
- const i18nRouteParams = { de: { param1: 'value1' } }
104
- const newRoute = routeService.switchLocaleRoute('en', 'de', route, i18nRouteParams)
105
- expect(newRoute).toEqual({
106
- name: 'localized-about',
107
- hash: undefined,
108
- query: undefined,
109
- params: { param1: 'value1', locale: 'de' },
110
- })
111
- })
112
-
113
- test('getLocalizedRoute should return the correct localized route', () => {
114
- const route = { name: 'about', params: {} } as RouteLocationNormalizedLoaded
115
- const to = { path: '/about' } as RouteLocationResolvedGeneric
116
- mockRouter.resolve.mockReturnValueOnce({
117
- fullPath: '/en/about',
118
- path: '/about',
119
- query: {},
120
- hash: '',
121
- params: {},
122
- } as RouteLocationResolvedGeneric)
123
- const localizedRoute = routeService.getLocalizedRoute(to, route, 'en')
124
- expect(localizedRoute).toEqual({
125
- path: '/about',
126
- fullPath: '/about',
127
- query: {},
128
- params: {},
129
- hash: '',
130
- })
131
- })
132
-
133
- test('switchLocaleLogic should switch the locale and navigate to the new route', async () => {
134
- const route = { name: 'about-en', params: {} } as RouteLocationResolvedGeneric
135
- const i18nRouteParams = { de: { param1: 'value1' } }
136
- await routeService.switchLocaleLogic('de', i18nRouteParams, route)
137
-
138
- // Check that push was called with correct arguments
139
- expect(mockRouter.push).toHaveBeenCalledWith({
140
- name: 'localized-about',
141
- params: { param1: 'value1', locale: 'de' },
142
- hash: undefined,
143
- query: undefined,
144
- })
145
- })
146
-
147
- test('getFullPathWithBaseUrl should return the correct full path with base URL', () => {
148
- const currentLocale = { code: 'de', iso: 'de-DE', baseUrl: 'https://example.com/de' }
149
- const route = { path: '/about' } as RouteLocationRaw
150
- const fullPath = routeService.getFullPathWithBaseUrl(currentLocale, route)
151
- expect(fullPath).toBe('https://example.com/de/about')
152
- })
153
-
154
- test('resolveLocalizedRoute should return the correct localized route', () => {
155
- const to = { path: '/about' } as RouteLocationAsPathGeneric
156
- mockRouter.resolve.mockReturnValueOnce({
157
- fullPath: '/en/about',
158
- path: '/about',
159
- query: {},
160
- hash: '',
161
- params: {},
162
- } as RouteLocationResolvedGeneric)
163
- const localizedRoute = routeService.resolveLocalizedRoute(to, 'en')
164
- expect(localizedRoute).toEqual({
165
- path: '/about',
166
- fullPath: '/about',
167
- query: {},
168
- params: {},
169
- hash: '',
170
- })
171
- })
172
-
173
- test('getCurrentLocale should return defaultLocale if locale is missing in route params', () => {
174
- mockRouter.currentRoute.value.params = {} // Remove locale from params
175
- mockRouter.currentRoute.value.path = '/' // No locale in path
176
- const locale = routeService.getCurrentLocale()
177
- expect(locale).toBe('en') // defaultLocale
178
- })
179
-
180
- test('getCurrentLocale should extract locale from URL path when route params are missing', () => {
181
- mockRouter.currentRoute.value.params = {} // Remove locale from params
182
- mockRouter.currentRoute.value.path = '/ru/sdfsdf' // URL with locale prefix
183
- const locale = routeService.getCurrentLocale()
184
- expect(locale).toBe('ru') // Should extract from URL
185
- })
186
-
187
- test('getCurrentLocale should return defaultLocale for prefix_except_default when URL has no locale prefix', () => {
188
- routeService = new RouteService(
189
- mockI18nConfig, // strategy: prefix_except_default
190
- mockRouter,
191
- null,
192
- null,
193
- navigateToMock,
194
- () => 'de', // getter from plugin (cookie/state)
195
- )
196
- mockRouter.currentRoute.value.params = {} // Remove locale from params
197
- mockRouter.currentRoute.value.path = '/' // No locale in path
198
- const locale = routeService.getCurrentLocale()
199
- // For prefix_except_default: URL without locale = defaultLocale (SEO requirement)
200
- // Getter is NOT used because URL explicitly indicates defaultLocale
201
- expect(locale).toBe('en')
202
- })
203
-
204
- test('getCurrentLocale should use getDefaultLocale for no_prefix strategy', () => {
205
- const noPrefixConfig = { ...mockI18nConfig, strategy: 'no_prefix' as const }
206
- routeService = new RouteService(
207
- noPrefixConfig,
208
- mockRouter,
209
- null,
210
- 'de', // noPrefixDefault
211
- navigateToMock,
212
- () => 'de', // getter from plugin (cookie/state)
213
- )
214
- mockRouter.currentRoute.value.params = {} // Remove locale from params
215
- mockRouter.currentRoute.value.path = '/' // No locale in path
216
- const locale = routeService.getCurrentLocale()
217
- // For no_prefix: getter/noPrefixDefault determines locale
218
- expect(locale).toBe('de')
219
- })
220
-
221
- test('getCurrentLocale should prioritize route params over URL path', () => {
222
- mockRouter.currentRoute.value.params = { locale: 'de' } // Route params have locale
223
- mockRouter.currentRoute.value.path = '/ru/sdfsdf' // URL has different locale
224
- const locale = routeService.getCurrentLocale()
225
- expect(locale).toBe('de') // Should use route params
226
- })
227
-
228
- test('getCurrentLocale should prioritize URL path over getDefaultLocale', () => {
229
- routeService = new RouteService(
230
- mockI18nConfig,
231
- mockRouter,
232
- null,
233
- null,
234
- navigateToMock,
235
- () => 'de', // getter
236
- )
237
- mockRouter.currentRoute.value.params = {} // No locale in params
238
- mockRouter.currentRoute.value.path = '/ru/sdfsdf' // URL has locale
239
- const locale = routeService.getCurrentLocale()
240
- expect(locale).toBe('ru') // Should use URL path, not getter
241
- })
242
-
243
- test('getCurrentName should return null if displayName is missing', () => {
244
- const mockI18nConfigWithoutDisplayName = {
245
- ...mockI18nConfig,
246
- locales: [
247
- { code: 'en', iso: 'en-US' }, // displayName is missing
248
- { code: 'de', iso: 'de-DE' },
249
- { code: 'ru', iso: 'ru-RU' },
250
- ],
251
- }
252
- routeService = new RouteService(mockI18nConfigWithoutDisplayName, mockRouter, null, null, navigateToMock)
253
- const route = { name: 'localized-about-en' } as RouteLocationNormalizedLoaded
254
- const displayName = routeService.getCurrentName(route)
255
- expect(displayName).toBeNull()
256
- })
257
-
258
- test('switchLocaleRoute should handle missing i18nRouteParams', () => {
259
- const route = { name: 'localized-about-en', params: {} } as RouteLocationResolvedGeneric
260
- const newRoute = routeService.switchLocaleRoute('en', 'de', route, {})
261
- expect(newRoute).toEqual({
262
- name: 'localized-about',
263
- hash: undefined,
264
- query: undefined,
265
- params: { locale: 'de' },
266
- })
267
- })
268
-
269
- test('getFullPathWithBaseUrl should handle missing baseUrl', () => {
270
- const currentLocale = { code: 'de', iso: 'de-DE' } // baseUrl is missing
271
- const route = { path: '/about' } as RouteLocationRaw
272
- const fullPath = routeService.getFullPathWithBaseUrl(currentLocale, route)
273
- expect(fullPath).toBe('/about')
274
- })
275
-
276
- test('handlePrefixStrategy should handle invalid route', () => {
277
- const to = '/invalid-route'
278
- mockRouter.resolve.mockReturnValueOnce({
279
- fullPath: '/invalid-route',
280
- path: '/invalid-route',
281
- query: {},
282
- hash: '',
283
- params: {},
284
- } as RouteLocationResolvedGeneric)
285
- const processedTo = routeService['handlePrefixStrategy'](to)
286
- expect(processedTo).toEqual(to)
287
- })
288
-
289
- test('createLocalizedRoute should handle invalid route', () => {
290
- const to = '/invalid-route'
291
- const route = { name: 'about', params: {} } as RouteLocationNormalizedLoaded
292
- mockRouter.resolve.mockReturnValueOnce({
293
- fullPath: '/invalid-route',
294
- path: '/invalid-route',
295
- query: {},
296
- hash: '',
297
- params: {},
298
- } as RouteLocationResolvedGeneric)
299
- const localizedRoute = routeService['createLocalizedRoute'](to, route, 'en')
300
- expect(localizedRoute).toEqual({
301
- path: '/invalid-route',
302
- fullPath: '/invalid-route',
303
- query: {},
304
- params: {},
305
- hash: '',
306
- })
307
- })
308
-
309
- test('resolveLocalizedRoute should handle invalid route', () => {
310
- const to = '/invalid-route'
311
- mockRouter.resolve.mockReturnValueOnce({
312
- fullPath: '/invalid-route',
313
- path: '/invalid-route',
314
- query: {},
315
- hash: '',
316
- params: {},
317
- } as RouteLocationResolvedGeneric)
318
- const localizedRoute = routeService.resolveLocalizedRoute(to, 'en')
319
- expect(localizedRoute).toEqual({
320
- path: '/invalid-route',
321
- fullPath: '/invalid-route',
322
- query: {},
323
- params: {},
324
- hash: '',
325
- })
326
- })
327
-
328
- test('getCurrentLocale should extract locale from fullPath with query params when route.path is missing', () => {
329
- mockRouter.currentRoute.value.params = {}
330
- mockRouter.currentRoute.value.path = '' // Simulate missing path (e.g. error state)
331
- mockRouter.currentRoute.value.fullPath = '/de?foo=bar&baz=qux' // Fallback uses fullPath
332
-
333
- // Ensure 'de' is in the config locales for this test
334
- // (It is already present in mockI18nConfig in beforeEach)
335
-
336
- const locale = routeService.getCurrentLocale()
337
- expect(locale).toBe('de')
338
- })
339
-
340
- test('getCurrentLocale should extract locale from path with hash', () => {
341
- mockRouter.currentRoute.value.params = {}
342
- mockRouter.currentRoute.value.path = ''
343
- mockRouter.currentRoute.value.fullPath = '/de#section'
344
- const locale = routeService.getCurrentLocale()
345
- expect(locale).toBe('de')
346
- })
347
- })