]> git.ipfire.org Git - thirdparty/vuejs/router.git/commitdiff
test: add tests for encoding
authorEduardo San Martin Morote <posva13@gmail.com>
Wed, 5 Feb 2020 10:54:05 +0000 (11:54 +0100)
committerEduardo San Martin Morote <posva13@gmail.com>
Wed, 5 Feb 2020 13:08:29 +0000 (14:08 +0100)
__tests__/mockWarn.ts [new file with mode: 0644]
__tests__/parseQuery.spec.ts [new file with mode: 0644]
__tests__/stringifyQuery.spec.ts [new file with mode: 0644]
__tests__/url.spec.ts
src/router.ts

diff --git a/__tests__/mockWarn.ts b/__tests__/mockWarn.ts
new file mode 100644 (file)
index 0000000..e080d95
--- /dev/null
@@ -0,0 +1,103 @@
+declare global {
+  namespace jest {
+    interface Matchers<R, T> {
+      toHaveBeenWarned(): R
+      toHaveBeenWarnedLast(): R
+      toHaveBeenWarnedTimes(n: number): R
+    }
+  }
+}
+
+export function mockWarn() {
+  expect.extend({
+    toHaveBeenWarned(received: string) {
+      asserted.add(received)
+      const passed = warn.mock.calls.some(
+        args => args[0].indexOf(received) > -1
+      )
+      if (passed) {
+        return {
+          pass: true,
+          message: () => `expected "${received}" not to have been warned.`,
+        }
+      } else {
+        const msgs = warn.mock.calls.map(args => args[0]).join('\n - ')
+        return {
+          pass: false,
+          message: () =>
+            `expected "${received}" to have been warned.\n\nActual messages:\n\n - ${msgs}`,
+        }
+      }
+    },
+
+    toHaveBeenWarnedLast(received: string) {
+      asserted.add(received)
+      const passed =
+        warn.mock.calls[warn.mock.calls.length - 1][0].indexOf(received) > -1
+      if (passed) {
+        return {
+          pass: true,
+          message: () => `expected "${received}" not to have been warned last.`,
+        }
+      } else {
+        const msgs = warn.mock.calls.map(args => args[0]).join('\n - ')
+        return {
+          pass: false,
+          message: () =>
+            `expected "${received}" to have been warned last.\n\nActual messages:\n\n - ${msgs}`,
+        }
+      }
+    },
+
+    toHaveBeenWarnedTimes(received: string, n: number) {
+      asserted.add(received)
+      let found = 0
+      warn.mock.calls.forEach(args => {
+        if (args[0].indexOf(received) > -1) {
+          found++
+        }
+      })
+
+      if (found === n) {
+        return {
+          pass: true,
+          message: () =>
+            `expected "${received}" to have been warned ${n} times.`,
+        }
+      } else {
+        return {
+          pass: false,
+          message: () =>
+            `expected "${received}" to have been warned ${n} times but got ${found}.`,
+        }
+      }
+    },
+  })
+
+  let warn: jest.SpyInstance
+  const asserted: Set<string> = new Set()
+
+  beforeEach(() => {
+    asserted.clear()
+    warn = jest.spyOn(console, 'warn')
+    warn.mockImplementation(() => {})
+  })
+
+  afterEach(() => {
+    const assertedArray = Array.from(asserted)
+    const nonAssertedWarnings = warn.mock.calls
+      .map(args => args[0])
+      .filter(received => {
+        return !assertedArray.some(assertedMsg => {
+          return received.indexOf(assertedMsg) > -1
+        })
+      })
+    warn.mockRestore()
+    if (nonAssertedWarnings.length) {
+      nonAssertedWarnings.forEach(warning => {
+        console.warn(warning)
+      })
+      throw new Error(`test case threw unexpected warnings.`)
+    }
+  })
+}
diff --git a/__tests__/parseQuery.spec.ts b/__tests__/parseQuery.spec.ts
new file mode 100644 (file)
index 0000000..fd7988a
--- /dev/null
@@ -0,0 +1,29 @@
+import { parseQuery } from '../src/history/common'
+import { mockWarn } from './mockWarn'
+
+describe('parseQuery', () => {
+  mockWarn()
+  it('decodes values in query', () => {
+    expect(parseQuery('e=%25')).toEqual({
+      e: '%',
+    })
+  })
+
+  it('decodes array values in query', () => {
+    expect(parseQuery('e=%25&e=%22')).toEqual({
+      e: ['%', '"'],
+    })
+    expect(parseQuery('e=%25&e=a')).toEqual({
+      e: ['%', 'a'],
+    })
+  })
+
+  // this is for browsers like IE that allow invalid characters
+  it('keep invalid values as is', () => {
+    expect(parseQuery('e=%&e=%25')).toEqual({
+      e: ['%', '%'],
+    })
+
+    expect('decoding "%"').toHaveBeenWarnedTimes(1)
+  })
+})
diff --git a/__tests__/stringifyQuery.spec.ts b/__tests__/stringifyQuery.spec.ts
new file mode 100644 (file)
index 0000000..8ea5a46
--- /dev/null
@@ -0,0 +1,22 @@
+import { stringifyQuery } from '../src/history/common'
+import { mockWarn } from './mockWarn'
+
+describe('stringifyQuery', () => {
+  mockWarn()
+
+  it('stringifies multiple values', () => {
+    expect(stringifyQuery({ e: 'a', b: 'c' })).toEqual('e=a&b=c')
+  })
+
+  it('stringifies arrays', () => {
+    expect(stringifyQuery({ e: ['b', 'a'] })).toEqual('e=b&e=a')
+  })
+
+  it('encodes values', () => {
+    expect(stringifyQuery({ e: '%', b: 'c' })).toEqual('e=%25&b=c')
+  })
+
+  it('encodes values in arrays', () => {
+    expect(stringifyQuery({ e: ['%', 'a'], b: 'c' })).toEqual('e=%25&e=a&b=c')
+  })
+})
index 3853b51d8d534ec9eb4214ebb9669f2d714cb2c7..ea4fe7b12b3fdbe06a99bc4ed14edf02d328590a 100644 (file)
@@ -56,6 +56,13 @@ describe('parseURL', () => {
       query: { a: ['one', 'two', 'three'] },
     })
   })
+
+  it('calls parseQuery', () => {
+    const parseQuery = jest.fn()
+    originalParseURL(parseQuery, '/?é=é&é=a')
+    expect(parseQuery).toHaveBeenCalledTimes(1)
+    expect(parseQuery).toHaveBeenCalledWith('é=é&é=a')
+  })
 })
 
 describe('stringifyURL', () => {
@@ -114,6 +121,16 @@ describe('stringifyURL', () => {
       })
     ).toBe('/path?foo=a&bar=b#hey')
   })
+
+  it('calls stringifyQuery', () => {
+    const stringifyQuery = jest.fn()
+    originalStringifyURL(stringifyQuery, {
+      path: '/',
+      query: { é: 'é', b: 'a' },
+    })
+    expect(stringifyQuery).toHaveBeenCalledTimes(1)
+    expect(stringifyQuery).toHaveBeenCalledWith({ é: 'é', b: 'a' })
+  })
 })
 
 describe('normalizeLocation', () => {
index 258938c5c2d47bc48bdc43593d37d64eb25dc99c..7fd6b43c4e15979a7e6659eeeb2a2c7d164c1b35 100644 (file)
@@ -168,7 +168,6 @@ export function createRouter({
     // const objectLocation = routerLocationAsObject(location)
     if (typeof location === 'string') {
       // TODO: remove as cast when redirect is removed from matcher
-      // TODO: ensure parseURL encodes the query in fullPath but not in query object
       let locationNormalized = parseURL(parseQuery, location)
       let matchedRoute = matcher.resolve(
         { path: locationNormalized.path },