Skip to content

Commit 1791759

Browse files
TheNorthMemoryshockey
authored andcommitted
improve(deeplink): support utf16 tags and IDs (via #4921)
* ref #3958, support utf16 fragments on the deeplink plugin * put -> head for UTF16 operation this is a temporary fix, eventually we will run out of methods and need to use a new targeting strategy * drop obsolete %20 decoder * add full test suite for UTF16 operation * use encodeURIComponent when setting hash * drop obsolete test cases
1 parent 3c3b7e0 commit 1791759

File tree

5 files changed

+87
-8
lines changed

5 files changed

+87
-8
lines changed

src/core/plugins/deep-linking/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ export default function() {
99
wrapActions: {
1010
loaded: (ori, system) => (...args) => {
1111
ori(...args)
12-
const hash = window.location.hash
12+
// location.hash was an UTF-16 String, here is required UTF-8
13+
const hash = decodeURIComponent(window.location.hash)
1314
system.layoutActions.parseDeepLinkHash(hash)
1415
}
1516
}

src/core/plugins/deep-linking/layout.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ export const show = (ori, { getConfigs, layoutSelectors }) => (...args) => {
3232
}
3333

3434
if (urlHashArray.length === 2) {
35-
setHash(createDeepLinkPath(`/${type}/${assetName}`))
35+
setHash(createDeepLinkPath(`/${encodeURIComponent(type)}/${encodeURIComponent(assetName)}`))
3636
} else if (urlHashArray.length === 1) {
37-
setHash(createDeepLinkPath(`/${type}`))
37+
setHash(createDeepLinkPath(`/${encodeURIComponent(type)}`))
3838
}
3939

4040
} catch (e) {
@@ -73,7 +73,7 @@ export const parseDeepLinkHash = (rawHash) => ({ layoutActions, layoutSelectors,
7373
hash = hash.slice(1)
7474
}
7575

76-
const hashArray = hash.split("/").map(val => (val || "").replace(/%20/g, " "))
76+
const hashArray = hash.split("/").map(val => (val || ""))
7777

7878
const isShownKey = layoutSelectors.isShownKeyFromUrlHashArray(hashArray)
7979

test/e2e-cypress/static/documents/features/deep-linking.openapi.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ paths:
2525
application/json:
2626
schema:
2727
type: object
28+
/utf16fragments:
29+
head:
30+
operationId: "пошел"
31+
tags: ["шеллы"]
32+
summary: an operation
33+
responses:
34+
"200":
35+
description: ok
2836
/withUnderscores:
2937
patch:
3038
operationId: "underscore_Operation"

test/e2e-cypress/static/documents/features/deep-linking.swagger.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ paths:
1717
responses:
1818
"200":
1919
description: ok
20+
/utf16fragments:
21+
head:
22+
operationId: "пошел"
23+
tags: ["шеллы"]
2024
/withUnderscores:
2125
patch:
2226
operationId: "underscore_Operation"
@@ -28,7 +32,3 @@ paths:
2832
/noOperationId:
2933
put:
3034
tags: ["tagTwo"]
31-
summary: an operation
32-
responses:
33-
"200":
34-
description: ok

test/e2e-cypress/tests/deep-linking.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,41 @@ describe("Deep linking feature", () => {
114114
})
115115
})
116116

117+
describe("Operation with UTF-16 characters", () => {
118+
const elementToGet = ".opblock-head"
119+
const correctElementId = "operations-шеллы-пошел"
120+
const correctFragment = "#/%D1%88%D0%B5%D0%BB%D0%BB%D1%8B/%D0%BF%D0%BE%D1%88%D0%B5%D0%BB"
121+
const correctHref = "#/шеллы/пошел"
122+
123+
it("should generate a correct element ID", () => {
124+
cy.get(elementToGet)
125+
.should("have.id", correctElementId)
126+
})
127+
128+
it("should add the correct element fragment to the URL when expanded", () => {
129+
cy.get(elementToGet)
130+
.click()
131+
.window()
132+
.should("have.deep.property", "location.hash", correctFragment)
133+
})
134+
135+
it("should provide an anchor link that has the correct fragment as href", () => {
136+
cy.get(elementToGet)
137+
.find("a")
138+
.should("have.attr", "href", correctHref)
139+
.click()
140+
.should("have.attr", "href", correctHref) // should be valid after expanding
141+
142+
})
143+
144+
it("should expand the operation when reloaded", () => {
145+
cy.visit(`${baseUrl}${correctFragment}`)
146+
.reload()
147+
.get(`${elementToGet}.is-open`)
148+
.should("exist")
149+
})
150+
})
151+
117152
describe("Operation with no operationId", () => {
118153
const elementToGet = ".opblock-put"
119154
const correctElementId = "operations-tagTwo-put_noOperationId"
@@ -276,6 +311,41 @@ describe("Deep linking feature", () => {
276311
})
277312
})
278313

314+
describe("Operation with UTF-16 characters", () => {
315+
const elementToGet = ".opblock-head"
316+
const correctElementId = "operations-шеллы-пошел"
317+
const correctFragment = "#/%D1%88%D0%B5%D0%BB%D0%BB%D1%8B/%D0%BF%D0%BE%D1%88%D0%B5%D0%BB"
318+
const correctHref = "#/шеллы/пошел"
319+
320+
it("should generate a correct element ID", () => {
321+
cy.get(elementToGet)
322+
.should("have.id", correctElementId)
323+
})
324+
325+
it("should add the correct element fragment to the URL when expanded", () => {
326+
cy.get(elementToGet)
327+
.click()
328+
.window()
329+
.should("have.deep.property", "location.hash", correctFragment)
330+
})
331+
332+
it("should provide an anchor link that has the correct fragment as href", () => {
333+
cy.get(elementToGet)
334+
.find("a")
335+
.should("have.attr", "href", correctHref)
336+
.click()
337+
.should("have.attr", "href", correctHref) // should be valid after expanding
338+
339+
})
340+
341+
it("should expand the operation when reloaded", () => {
342+
cy.visit(`${baseUrl}${correctFragment}`)
343+
.reload()
344+
.get(`${elementToGet}.is-open`)
345+
.should("exist")
346+
})
347+
})
348+
279349
describe("Operation with no operationId", () => {
280350
const elementToGet = ".opblock-put"
281351
const correctElementId = "operations-tagTwo-put_noOperationId"

0 commit comments

Comments
 (0)