@avalix/chroma 0.0.11 → 0.0.13

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.
@@ -0,0 +1,106 @@
1
+ import type { BrowserContext, Page } from '@playwright/test'
2
+ import { beforeEach, describe, expect, it, vi } from 'vitest'
3
+ import {
4
+ createPolkadotJsWallet,
5
+ createTalismanWallet,
6
+ walletFactories,
7
+ } from './wallet-factory.js'
8
+
9
+ // Mock wallet implementations
10
+ vi.mock('../wallets/polkadot-js.js', () => ({
11
+ importPolkadotJSAccount: vi.fn(),
12
+ authorizePolkadotJS: vi.fn(),
13
+ approvePolkadotJSTx: vi.fn(),
14
+ rejectPolkadotJSTx: vi.fn(),
15
+ }))
16
+
17
+ vi.mock('../wallets/talisman.js', () => ({
18
+ importPolkadotMnemonic: vi.fn(),
19
+ importEthPrivateKey: vi.fn(),
20
+ authorizeTalisman: vi.fn(),
21
+ approveTalismanTx: vi.fn(),
22
+ rejectTalismanTx: vi.fn(),
23
+ }))
24
+
25
+ // Create mock browser context
26
+ function createMockContext(): BrowserContext {
27
+ const mockPage = {
28
+ url: () => 'https://example.com',
29
+ __extensionContext: null,
30
+ __extensionId: '',
31
+ } as unknown as Page
32
+
33
+ return {
34
+ pages: vi.fn().mockReturnValue([mockPage]),
35
+ newPage: vi.fn().mockResolvedValue(mockPage),
36
+ } as unknown as BrowserContext
37
+ }
38
+
39
+ describe('wallet-factory', () => {
40
+ beforeEach(() => {
41
+ vi.clearAllMocks()
42
+ })
43
+
44
+ describe('walletFactories', () => {
45
+ it('should have polkadot-js factory', () => {
46
+ expect(walletFactories['polkadot-js']).toBeDefined()
47
+ expect(typeof walletFactories['polkadot-js']).toBe('function')
48
+ })
49
+
50
+ it('should have talisman factory', () => {
51
+ expect(walletFactories.talisman).toBeDefined()
52
+ expect(typeof walletFactories.talisman).toBe('function')
53
+ })
54
+ })
55
+
56
+ describe('createPolkadotJsWallet', () => {
57
+ const extensionId = 'test-extension-id'
58
+ let mockContext: BrowserContext
59
+
60
+ beforeEach(() => {
61
+ mockContext = createMockContext()
62
+ })
63
+
64
+ it('should create wallet with correct type and extensionId', () => {
65
+ const wallet = createPolkadotJsWallet(extensionId, mockContext)
66
+
67
+ expect(wallet.type).toBe('polkadot-js')
68
+ expect(wallet.extensionId).toBe(extensionId)
69
+ })
70
+
71
+ it('should have all required methods', () => {
72
+ const wallet = createPolkadotJsWallet(extensionId, mockContext)
73
+
74
+ expect(typeof wallet.importMnemonic).toBe('function')
75
+ expect(typeof wallet.authorize).toBe('function')
76
+ expect(typeof wallet.approveTx).toBe('function')
77
+ expect(typeof wallet.rejectTx).toBe('function')
78
+ })
79
+ })
80
+
81
+ describe('createTalismanWallet', () => {
82
+ const extensionId = 'test-extension-id'
83
+ let mockContext: BrowserContext
84
+
85
+ beforeEach(() => {
86
+ mockContext = createMockContext()
87
+ })
88
+
89
+ it('should create wallet with correct type and extensionId', () => {
90
+ const wallet = createTalismanWallet(extensionId, mockContext)
91
+
92
+ expect(wallet.type).toBe('talisman')
93
+ expect(wallet.extensionId).toBe(extensionId)
94
+ })
95
+
96
+ it('should have all required methods', () => {
97
+ const wallet = createTalismanWallet(extensionId, mockContext)
98
+
99
+ expect(typeof wallet.importPolkadotMnemonic).toBe('function')
100
+ expect(typeof wallet.importEthPrivateKey).toBe('function')
101
+ expect(typeof wallet.authorize).toBe('function')
102
+ expect(typeof wallet.approveTx).toBe('function')
103
+ expect(typeof wallet.rejectTx).toBe('function')
104
+ })
105
+ })
106
+ })
@@ -1,11 +1,5 @@
1
1
  import type { BrowserContext, Page } from '@playwright/test'
2
- import type {
3
- BaseWalletInstance,
4
- PolkadotJsWalletInstance,
5
- TalismanWalletInstance,
6
- WalletAccount,
7
- WalletInstance,
8
- } from './types.js'
2
+ import type { WalletAccount } from './types.js'
9
3
  import {
10
4
  approvePolkadotJSTx,
11
5
  authorizePolkadotJS,
@@ -16,125 +10,107 @@ import {
16
10
  approveTalismanTx,
17
11
  authorizeTalisman,
18
12
  importEthPrivateKey,
13
+ importPolkadotMnemonic,
19
14
  rejectTalismanTx,
20
15
  } from '../wallets/talisman.js'
21
16
 
22
17
  // Helper to create extended page with wallet context
18
+ /* c8 ignore start */
23
19
  function createExtendedPage(page: Page, context: BrowserContext, extensionId: string) {
24
20
  const extPage = page as Page & { __extensionContext: BrowserContext, __extensionId: string }
25
21
  extPage.__extensionContext = context
26
22
  extPage.__extensionId = extensionId
27
23
  return extPage
28
24
  }
25
+ /* c8 ignore stop */
29
26
 
30
- // Create wallet instance helper with proper typing
31
- export function createWalletInstance(
32
- walletType: string,
33
- extensionId: string,
34
- context: BrowserContext,
35
- ): WalletInstance {
36
- // Store the imported account name for later use
37
- let importedAccountName: string | undefined
38
-
39
- // Common methods for all wallets
40
- const baseInstance: BaseWalletInstance = {
27
+ /*
28
+ * Factory function for Polkadot-JS wallet
29
+ * Coverage excluded: methods interact with Chrome extension APIs via browser context.
30
+ */
31
+ /* c8 ignore start */
32
+ export function createPolkadotJsWallet(extensionId: string, context: BrowserContext) {
33
+ return {
41
34
  extensionId,
35
+ type: 'polkadot-js' as const,
42
36
  importMnemonic: async (options: WalletAccount) => {
43
37
  const page = context.pages()[0] || await context.newPage()
44
38
  const extPage = createExtendedPage(page, context, extensionId)
39
+ await importPolkadotJSAccount(extPage, options)
40
+ },
41
+ authorize: async () => {
42
+ const page = context.pages()[0] || await context.newPage()
43
+ const extPage = createExtendedPage(page, context, extensionId)
44
+ await authorizePolkadotJS(extPage)
45
+ },
46
+ approveTx: async (options: { password?: string } = {}) => {
47
+ const page = context.pages()[0] || await context.newPage()
48
+ const extPage = createExtendedPage(page, context, extensionId)
49
+ await approvePolkadotJSTx(extPage, options)
50
+ },
51
+ rejectTx: async () => {
52
+ const page = context.pages()[0] || await context.newPage()
53
+ const extPage = createExtendedPage(page, context, extensionId)
54
+ await rejectPolkadotJSTx(extPage)
55
+ },
56
+ }
57
+ }
58
+ /* c8 ignore stop */
45
59
 
46
- // Store the account name for future authorize calls
47
- importedAccountName = options.name || 'Test Account'
60
+ /*
61
+ * Factory function for Talisman wallet
62
+ * Coverage excluded: methods interact with Chrome extension APIs via browser context.
63
+ */
64
+ /* c8 ignore start */
65
+ export function createTalismanWallet(extensionId: string, context: BrowserContext) {
66
+ let importedAccountName: string | undefined
48
67
 
49
- switch (walletType) {
50
- case 'polkadot-js':
51
- await importPolkadotJSAccount(extPage, options)
52
- break
53
- case 'talisman':
54
- throw new Error('Talisman importMnemonic is not yet implemented.')
55
- default:
56
- throw new Error(`Unsupported wallet type: ${walletType}`)
57
- }
68
+ return {
69
+ extensionId,
70
+ type: 'talisman' as const,
71
+ importPolkadotMnemonic: async (options: WalletAccount) => {
72
+ const page = context.pages()[0] || await context.newPage()
73
+ const extPage = createExtendedPage(page, context, extensionId)
74
+ importedAccountName = options.name || 'Test Account'
75
+ await importPolkadotMnemonic(extPage, options)
76
+ },
77
+ importEthPrivateKey: async (options: { privateKey: string, name?: string, password?: string }) => {
78
+ const page = context.pages()[0] || await context.newPage()
79
+ const extPage = createExtendedPage(page, context, extensionId)
80
+ importedAccountName = options.name || 'Test Account'
81
+ await importEthPrivateKey(extPage, {
82
+ seed: options.privateKey,
83
+ name: options.name,
84
+ password: options.password,
85
+ })
58
86
  },
59
87
  authorize: async (options: { accountName?: string } = {}) => {
60
88
  const page = context.pages()[0] || await context.newPage()
61
89
  const extPage = createExtendedPage(page, context, extensionId)
62
-
63
- // Use provided account name or fall back to the imported one
64
90
  const accountName = options.accountName || importedAccountName
65
-
66
- switch (walletType) {
67
- case 'polkadot-js':
68
- await authorizePolkadotJS(extPage)
69
- break
70
- case 'talisman':
71
- await authorizeTalisman(extPage, { accountName })
72
- break
73
- default:
74
- throw new Error(`Unsupported wallet type: ${walletType}`)
75
- }
91
+ await authorizeTalisman(extPage, { accountName })
76
92
  },
77
- approveTx: async (options: { password?: string } = {}) => {
93
+ approveTx: async () => {
78
94
  const page = context.pages()[0] || await context.newPage()
79
95
  const extPage = createExtendedPage(page, context, extensionId)
80
-
81
- switch (walletType) {
82
- case 'polkadot-js':
83
- await approvePolkadotJSTx(extPage, options)
84
- break
85
- case 'talisman':
86
- await approveTalismanTx(extPage)
87
- break
88
- default:
89
- throw new Error(`Unsupported wallet type: ${walletType}`)
90
- }
96
+ await approveTalismanTx(extPage)
91
97
  },
92
98
  rejectTx: async () => {
93
99
  const page = context.pages()[0] || await context.newPage()
94
100
  const extPage = createExtendedPage(page, context, extensionId)
95
-
96
- switch (walletType) {
97
- case 'polkadot-js':
98
- await rejectPolkadotJSTx(extPage)
99
- break
100
- case 'talisman':
101
- await rejectTalismanTx(extPage)
102
- break
103
- default:
104
- throw new Error(`Unsupported wallet type: ${walletType}`)
105
- }
101
+ await rejectTalismanTx(extPage)
106
102
  },
107
103
  }
104
+ }
105
+ /* c8 ignore stop */
108
106
 
109
- // Return wallet-specific instance with type discriminator
110
- switch (walletType) {
111
- case 'polkadot-js':
112
- return {
113
- ...baseInstance,
114
- type: 'polkadot-js',
115
- } as PolkadotJsWalletInstance
116
-
117
- case 'talisman':
118
- return {
119
- ...baseInstance,
120
- type: 'talisman',
121
- importEthPrivateKey: async (options: { privateKey: string, name?: string, password?: string }) => {
122
- const page = context.pages()[0] || await context.newPage()
123
- const extPage = createExtendedPage(page, context, extensionId)
124
-
125
- // Store the account name for future authorize calls
126
- importedAccountName = options.name || 'Test Account'
127
-
128
- // Use the seed property to pass the private key
129
- await importEthPrivateKey(extPage, {
130
- seed: options.privateKey,
131
- name: options.name,
132
- password: options.password,
133
- })
134
- },
135
- } as TalismanWalletInstance
136
-
137
- default:
138
- throw new Error(`Unsupported wallet type: ${walletType}`)
139
- }
107
+ // Wallet factories map - auto-inferred types
108
+ export const walletFactories = {
109
+ 'polkadot-js': createPolkadotJsWallet,
110
+ 'talisman': createTalismanWallet,
140
111
  }
112
+
113
+ // Auto-inferred types from factory functions
114
+ export type PolkadotJsWalletInstance = ReturnType<typeof createPolkadotJsWallet>
115
+ export type TalismanWalletInstance = ReturnType<typeof createTalismanWallet>
116
+ export type WalletInstance = PolkadotJsWalletInstance | TalismanWalletInstance
@@ -0,0 +1,57 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+
3
+ // Mock playwright before importing
4
+ vi.mock('@playwright/test', () => ({
5
+ test: {
6
+ extend: vi.fn().mockReturnValue({}),
7
+ },
8
+ chromium: {
9
+ launchPersistentContext: vi.fn(),
10
+ },
11
+ expect: vi.fn(),
12
+ }))
13
+
14
+ vi.mock('./wallets/polkadot-js.js', () => ({
15
+ getPolkadotJSExtensionPath: vi.fn().mockResolvedValue('/mock/path'),
16
+ }))
17
+
18
+ vi.mock('./wallets/talisman.js', () => ({
19
+ getTalismanExtensionPath: vi.fn().mockResolvedValue('/mock/path'),
20
+ }))
21
+
22
+ vi.mock('./context-playwright/wallet-factory.js', () => ({
23
+ walletFactories: {
24
+ 'polkadot-js': vi.fn(),
25
+ 'talisman': vi.fn(),
26
+ },
27
+ }))
28
+
29
+ describe('index exports', () => {
30
+ it('should export createWalletTest function', async () => {
31
+ const { createWalletTest } = await import('./index.js')
32
+ expect(createWalletTest).toBeDefined()
33
+ expect(typeof createWalletTest).toBe('function')
34
+ })
35
+
36
+ it('should export test function', async () => {
37
+ const { test } = await import('./index.js')
38
+ expect(test).toBeDefined()
39
+ })
40
+
41
+ it('should export expect function', async () => {
42
+ const { expect: playwrightExpect } = await import('./index.js')
43
+ expect(playwrightExpect).toBeDefined()
44
+ })
45
+
46
+ it('should be able to call createWalletTest', async () => {
47
+ const { createWalletTest } = await import('./index.js')
48
+ const result = createWalletTest()
49
+ expect(result).toBeDefined()
50
+ })
51
+
52
+ it('should be able to call createWalletTest with options', async () => {
53
+ const { createWalletTest } = await import('./index.js')
54
+ const result = createWalletTest({ headless: true })
55
+ expect(result).toBeDefined()
56
+ })
57
+ })
@@ -34,7 +34,7 @@ export async function downloadAndExtractExtension(options: DownloadExtensionOpti
34
34
  }
35
35
 
36
36
  try {
37
- console.log(`📥 Downloading ${extensionName}...`)
37
+ console.log(`\n📥 Downloading ${extensionName}...`)
38
38
 
39
39
  // Download the ZIP file
40
40
  const response = await fetch(downloadUrl)
@@ -0,0 +1,97 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
4
+ import {
5
+ getPolkadotJSExtensionPath,
6
+ POLKADOT_JS_CONFIG,
7
+ } from './polkadot-js.js'
8
+
9
+ // Mock node:fs module
10
+ vi.mock('node:fs', async () => {
11
+ const actual = await vi.importActual<typeof import('node:fs')>('node:fs')
12
+ return {
13
+ ...actual,
14
+ default: {
15
+ ...actual,
16
+ existsSync: vi.fn(),
17
+ readdirSync: vi.fn(),
18
+ },
19
+ existsSync: vi.fn(),
20
+ readdirSync: vi.fn(),
21
+ }
22
+ })
23
+
24
+ describe('polkadot-js wallet', () => {
25
+ beforeEach(() => {
26
+ vi.clearAllMocks()
27
+ })
28
+
29
+ afterEach(() => {
30
+ vi.restoreAllMocks()
31
+ })
32
+
33
+ describe('polkadot_js_config', () => {
34
+ it('should have correct extension name format', () => {
35
+ expect(POLKADOT_JS_CONFIG.extensionName).toMatch(/^polkadot-extension-\d+\.\d+\.\d+$/)
36
+ })
37
+
38
+ it('should have valid download URL', () => {
39
+ expect(POLKADOT_JS_CONFIG.downloadUrl).toContain('github.com')
40
+ expect(POLKADOT_JS_CONFIG.downloadUrl).toContain('polkadot-js/extension')
41
+ expect(POLKADOT_JS_CONFIG.downloadUrl.endsWith('.zip')).toBe(true)
42
+ })
43
+ })
44
+
45
+ describe('getPolkadotJSExtensionPath', () => {
46
+ it('should return extension path when extension exists', async () => {
47
+ const mockedFs = vi.mocked(fs)
48
+ mockedFs.existsSync.mockReturnValue(true)
49
+ mockedFs.readdirSync.mockReturnValue(['manifest.json'] as any)
50
+
51
+ const result = await getPolkadotJSExtensionPath()
52
+
53
+ expect(result).toContain('.chroma')
54
+ expect(result).toContain(POLKADOT_JS_CONFIG.extensionName)
55
+ expect(mockedFs.existsSync).toHaveBeenCalled()
56
+ })
57
+
58
+ it('should throw error when extension directory does not exist', async () => {
59
+ const mockedFs = vi.mocked(fs)
60
+ mockedFs.existsSync.mockReturnValue(false)
61
+
62
+ await expect(getPolkadotJSExtensionPath()).rejects.toThrow(
63
+ 'Polkadot-JS extension not found',
64
+ )
65
+ })
66
+
67
+ it('should throw error when extension directory is empty', async () => {
68
+ const mockedFs = vi.mocked(fs)
69
+ mockedFs.existsSync.mockReturnValue(true)
70
+ mockedFs.readdirSync.mockReturnValue([])
71
+
72
+ await expect(getPolkadotJSExtensionPath()).rejects.toThrow(
73
+ 'Polkadot-JS extension not found',
74
+ )
75
+ })
76
+
77
+ it('should include download instructions in error message', async () => {
78
+ const mockedFs = vi.mocked(fs)
79
+ mockedFs.existsSync.mockReturnValue(false)
80
+
81
+ await expect(getPolkadotJSExtensionPath()).rejects.toThrow(
82
+ 'npx @avalix/chroma download-extensions',
83
+ )
84
+ })
85
+
86
+ it('should use correct path structure', async () => {
87
+ const mockedFs = vi.mocked(fs)
88
+ mockedFs.existsSync.mockReturnValue(true)
89
+ mockedFs.readdirSync.mockReturnValue(['manifest.json'] as any)
90
+
91
+ const result = await getPolkadotJSExtensionPath()
92
+
93
+ const expectedPath = path.join(process.cwd(), '.chroma', POLKADOT_JS_CONFIG.extensionName)
94
+ expect(result).toBe(expectedPath)
95
+ })
96
+ })
97
+ })
@@ -12,7 +12,11 @@ export const POLKADOT_JS_CONFIG = {
12
12
  extensionName: `polkadot-extension-${VERSION}`,
13
13
  } as const
14
14
 
15
- // Helper function to find extension popup
15
+ /*
16
+ * Helper function to find extension popup
17
+ * Coverage excluded: requires real browser context with Chrome extension APIs.
18
+ */
19
+ /* c8 ignore start */
16
20
  async function findExtensionPopup(context: BrowserContext, extensionId: string): Promise<Page> {
17
21
  // Wait for extension popup to appear with retry logic
18
22
  const maxAttempts = 10
@@ -35,6 +39,7 @@ async function findExtensionPopup(context: BrowserContext, extensionId: string):
35
39
 
36
40
  throw new Error(`Extension popup not found for ID: ${extensionId}`)
37
41
  }
42
+ /* c8 ignore stop */
38
43
 
39
44
  // Get Polkadot-JS extension path
40
45
  export async function getPolkadotJSExtensionPath(): Promise<string> {
@@ -53,6 +58,13 @@ export async function getPolkadotJSExtensionPath(): Promise<string> {
53
58
  return extensionDir
54
59
  }
55
60
 
61
+ /*
62
+ * Wallet interaction functions below are excluded from coverage because:
63
+ * - They require a real Chromium browser with extension support
64
+ * - They interact with Chrome extension popup pages
65
+ */
66
+ /* c8 ignore start */
67
+
56
68
  // Polkadot-JS specific account import implementation
57
69
  export async function importPolkadotJSAccount(
58
70
  page: Page & { __extensionContext: BrowserContext, __extensionId: string },
@@ -142,3 +154,5 @@ export async function rejectPolkadotJSTx(
142
154
  const extensionPopup = await findExtensionPopup(context, extensionId)
143
155
  await extensionPopup.getByRole('link', { name: 'Cancel' }).click()
144
156
  }
157
+
158
+ /* c8 ignore stop */
@@ -0,0 +1,97 @@
1
+ import fs from 'node:fs'
2
+ import path from 'node:path'
3
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
4
+ import {
5
+ getTalismanExtensionPath,
6
+ TALISMAN_CONFIG,
7
+ } from './talisman.js'
8
+
9
+ // Mock node:fs module
10
+ vi.mock('node:fs', async () => {
11
+ const actual = await vi.importActual<typeof import('node:fs')>('node:fs')
12
+ return {
13
+ ...actual,
14
+ default: {
15
+ ...actual,
16
+ existsSync: vi.fn(),
17
+ readdirSync: vi.fn(),
18
+ },
19
+ existsSync: vi.fn(),
20
+ readdirSync: vi.fn(),
21
+ }
22
+ })
23
+
24
+ describe('talisman wallet', () => {
25
+ beforeEach(() => {
26
+ vi.clearAllMocks()
27
+ })
28
+
29
+ afterEach(() => {
30
+ vi.restoreAllMocks()
31
+ })
32
+
33
+ describe('talisman_config', () => {
34
+ it('should have correct extension name format', () => {
35
+ expect(TALISMAN_CONFIG.extensionName).toMatch(/^talisman-extension-\d+\.\d+\.\d+$/)
36
+ })
37
+
38
+ it('should have valid download URL', () => {
39
+ expect(TALISMAN_CONFIG.downloadUrl).toContain('github.com')
40
+ expect(TALISMAN_CONFIG.downloadUrl).toContain('talisman')
41
+ expect(TALISMAN_CONFIG.downloadUrl.endsWith('.zip')).toBe(true)
42
+ })
43
+ })
44
+
45
+ describe('getTalismanExtensionPath', () => {
46
+ it('should return extension path when extension exists', async () => {
47
+ const mockedFs = vi.mocked(fs)
48
+ mockedFs.existsSync.mockReturnValue(true)
49
+ mockedFs.readdirSync.mockReturnValue(['manifest.json'] as any)
50
+
51
+ const result = await getTalismanExtensionPath()
52
+
53
+ expect(result).toContain('.chroma')
54
+ expect(result).toContain(TALISMAN_CONFIG.extensionName)
55
+ expect(mockedFs.existsSync).toHaveBeenCalled()
56
+ })
57
+
58
+ it('should throw error when extension directory does not exist', async () => {
59
+ const mockedFs = vi.mocked(fs)
60
+ mockedFs.existsSync.mockReturnValue(false)
61
+
62
+ await expect(getTalismanExtensionPath()).rejects.toThrow(
63
+ 'Talisman extension not found',
64
+ )
65
+ })
66
+
67
+ it('should throw error when extension directory is empty', async () => {
68
+ const mockedFs = vi.mocked(fs)
69
+ mockedFs.existsSync.mockReturnValue(true)
70
+ mockedFs.readdirSync.mockReturnValue([])
71
+
72
+ await expect(getTalismanExtensionPath()).rejects.toThrow(
73
+ 'Talisman extension not found',
74
+ )
75
+ })
76
+
77
+ it('should include download instructions in error message', async () => {
78
+ const mockedFs = vi.mocked(fs)
79
+ mockedFs.existsSync.mockReturnValue(false)
80
+
81
+ await expect(getTalismanExtensionPath()).rejects.toThrow(
82
+ 'npx @avalix/chroma download-extensions',
83
+ )
84
+ })
85
+
86
+ it('should use correct path structure', async () => {
87
+ const mockedFs = vi.mocked(fs)
88
+ mockedFs.existsSync.mockReturnValue(true)
89
+ mockedFs.readdirSync.mockReturnValue(['manifest.json'] as any)
90
+
91
+ const result = await getTalismanExtensionPath()
92
+
93
+ const expectedPath = path.join(process.cwd(), '.chroma', TALISMAN_CONFIG.extensionName)
94
+ expect(result).toBe(expectedPath)
95
+ })
96
+ })
97
+ })