sparkling-navigation 2.1.0-rc.2 → 2.1.0-rc.20
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.
- package/android/build.gradle.kts +1 -1
- package/dist/src/devServer.d.ts +10 -0
- package/dist/src/devServer.d.ts.map +1 -0
- package/dist/src/devServer.js +40 -0
- package/dist/src/devServer.js.map +1 -0
- package/dist/src/navigate/navigate.d.ts.map +1 -1
- package/dist/src/navigate/navigate.js +4 -12
- package/dist/src/navigate/navigate.js.map +1 -1
- package/dist/src/open/open.d.ts.map +1 -1
- package/dist/src/open/open.js +20 -1
- package/dist/src/open/open.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/ios/Sparkling-Router.podspec +7 -11
- package/package.json +2 -2
- package/src/__tests__/navigate/navigate.test.ts +70 -1
- package/src/devServer.ts +44 -0
- package/src/navigate/navigate.ts +4 -15
- package/src/open/open.ts +20 -1
- package/ios/SparklingMethodTests/SPKRouterTest.swift +0 -124
package/android/build.gradle.kts
CHANGED
|
@@ -43,7 +43,7 @@ dependencies {
|
|
|
43
43
|
androidTestImplementation(libs.androidx.espresso.core)
|
|
44
44
|
val sparklingVersion = (findProperty("SPARKLING_ANDROID_SDK_VERSION") as? String)
|
|
45
45
|
?: System.getenv("SPARKLING_ANDROID_SDK_VERSION")
|
|
46
|
-
?: "2.
|
|
46
|
+
?: "2.1.0-rc.12"
|
|
47
47
|
api("com.tiktok.sparkling:sparkling-method:$sparklingVersion")
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive the dev server base URL from the actual bundle URL that the native
|
|
3
|
+
* side used to load this page. Falls back to __webpack_public_path__.
|
|
4
|
+
*
|
|
5
|
+
* This ensures sub-page navigation uses the same host/port that the entry
|
|
6
|
+
* page was loaded from — critical for real-device debugging where the native
|
|
7
|
+
* side may use a LAN IP while __webpack_public_path__ is baked as localhost.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getDevServerBaseURL(): string | undefined;
|
|
10
|
+
//# sourceMappingURL=devServer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devServer.d.ts","sourceRoot":"","sources":["../../src/devServer.ts"],"names":[],"mappings":"AAQA;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,GAAG,SAAS,CA2BxD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Copyright (c) 2022 TikTok Pte. Ltd.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
/**
|
|
5
|
+
* Derive the dev server base URL from the actual bundle URL that the native
|
|
6
|
+
* side used to load this page. Falls back to __webpack_public_path__.
|
|
7
|
+
*
|
|
8
|
+
* This ensures sub-page navigation uses the same host/port that the entry
|
|
9
|
+
* page was loaded from — critical for real-device debugging where the native
|
|
10
|
+
* side may use a LAN IP while __webpack_public_path__ is baked as localhost.
|
|
11
|
+
*/
|
|
12
|
+
export function getDevServerBaseURL() {
|
|
13
|
+
var _a, _b;
|
|
14
|
+
try {
|
|
15
|
+
if (typeof __DEV__ === 'undefined' || !__DEV__) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
// Prefer the actual URL the native side used to load this bundle.
|
|
19
|
+
// lynx.__globalProps.queryItems.url is set by the SDK from the scheme's
|
|
20
|
+
// url= parameter (e.g. "http://192.168.1.100:5969/main.lynx.bundle").
|
|
21
|
+
if (typeof lynx !== 'undefined' && ((_b = (_a = lynx === null || lynx === void 0 ? void 0 : lynx.__globalProps) === null || _a === void 0 ? void 0 : _a.queryItems) === null || _b === void 0 ? void 0 : _b.url)) {
|
|
22
|
+
const pageUrl = lynx.__globalProps.queryItems.url;
|
|
23
|
+
if (pageUrl.startsWith('http://') || pageUrl.startsWith('https://')) {
|
|
24
|
+
const lastSlash = pageUrl.lastIndexOf('/');
|
|
25
|
+
if (lastSlash > pageUrl.indexOf('//') + 1) {
|
|
26
|
+
return pageUrl.substring(0, lastSlash + 1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Fall back to build-time value.
|
|
31
|
+
if (typeof __webpack_public_path__ === 'string' && __webpack_public_path__) {
|
|
32
|
+
return __webpack_public_path__;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (_c) {
|
|
36
|
+
// globals not available
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=devServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devServer.js","sourceRoot":"","sources":["../../src/devServer.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,yEAAyE;AACzE,0DAA0D;AAM1D;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB;;IAC/B,IAAI,CAAC;QACD,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO,EAAE,CAAC;YAC7C,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,kEAAkE;QAClE,wEAAwE;QACxE,sEAAsE;QACtE,IAAI,OAAO,IAAI,KAAK,WAAW,KAAI,MAAA,MAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,aAAa,0CAAE,UAAU,0CAAE,GAAG,CAAA,EAAE,CAAC;YACtE,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC;YAClD,IAAI,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAClE,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;gBAC3C,IAAI,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACxC,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;gBAC/C,CAAC;YACL,CAAC;QACL,CAAC;QAED,iCAAiC;QACjC,IAAI,OAAO,uBAAuB,KAAK,QAAQ,IAAI,uBAAuB,EAAE,CAAC;YACzE,OAAO,uBAAuB,CAAC;QACnC,CAAC;IACL,CAAC;IAAC,WAAM,CAAC;QACL,wBAAwB;IAC5B,CAAC;IACD,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../../../src/navigate/navigate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"navigate.d.ts","sourceRoot":"","sources":["../../../src/navigate/navigate.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACR,eAAe,EACf,gBAAgB,EAGnB,MAAM,cAAc,CAAC;AAyDtB,wBAAgB,QAAQ,CAAC,MAAM,EAAE,eAAe,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI,CAgDpG"}
|
|
@@ -13,6 +13,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
13
13
|
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
14
14
|
// LICENSE file in the root directory of this source tree.
|
|
15
15
|
import { open } from '../open/open';
|
|
16
|
+
import { getDevServerBaseURL } from '../devServer';
|
|
16
17
|
const DEFAULT_ROUTER_SCHEME = 'hybrid://lynxview_page';
|
|
17
18
|
const PROTOCOL_REGEX = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
18
19
|
function createErrorResponse(msg) {
|
|
@@ -27,17 +28,6 @@ function normalizePath(path) {
|
|
|
27
28
|
normalized = normalized.replace(/^(?:\.\/|\/)+/, '');
|
|
28
29
|
return normalized;
|
|
29
30
|
}
|
|
30
|
-
function getDevServerBaseURL() {
|
|
31
|
-
try {
|
|
32
|
-
if (typeof __DEV__ !== 'undefined' && __DEV__ && typeof __webpack_public_path__ === 'string' && __webpack_public_path__) {
|
|
33
|
-
return __webpack_public_path__;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
catch (_a) {
|
|
37
|
-
// __DEV__ or __webpack_public_path__ not available
|
|
38
|
-
}
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
31
|
function buildScheme(baseScheme, bundlePath, params) {
|
|
42
32
|
const sanitizedBase = (baseScheme || DEFAULT_ROUTER_SCHEME).trim().replace(/[?&]+$/, '') || DEFAULT_ROUTER_SCHEME;
|
|
43
33
|
const searchParams = new URLSearchParams();
|
|
@@ -67,7 +57,9 @@ function buildScheme(baseScheme, bundlePath, params) {
|
|
|
67
57
|
searchParams.append(key, String(value));
|
|
68
58
|
}
|
|
69
59
|
}
|
|
70
|
-
|
|
60
|
+
// URLSearchParams encodes spaces as '+' (x-www-form-urlencoded), but
|
|
61
|
+
// native URL parsers only understand '%20'. Replace to avoid mangled values.
|
|
62
|
+
return `${sanitizedBase}?${searchParams.toString().replace(/\+/g, '%20')}`;
|
|
71
63
|
}
|
|
72
64
|
export function navigate(params, callback) {
|
|
73
65
|
var _a, _b;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../../src/navigate/navigate.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,sCAAsC;AACtC,yEAAyE;AACzE,0DAA0D;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"navigate.js","sourceRoot":"","sources":["../../../src/navigate/navigate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/open/open.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/open/open.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE1D;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI,CA2DxF"}
|
package/dist/src/open/open.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
3
|
// LICENSE file in the root directory of this source tree.
|
|
4
4
|
import pipe from 'sparkling-method';
|
|
5
|
+
import { getDevServerBaseURL } from '../devServer';
|
|
5
6
|
/**
|
|
6
7
|
* Open a new page or route
|
|
7
8
|
* @param params |
|
|
@@ -32,7 +33,25 @@ export function open(params, callback) {
|
|
|
32
33
|
console.error('[sparkling-navigation] open: callback must be a function');
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
// In dev mode, rewrite bundle= to url= so the native side loads from the
|
|
37
|
+
// dev server instead of stale local assets.
|
|
38
|
+
let scheme = params.scheme.trim();
|
|
39
|
+
const devBase = getDevServerBaseURL();
|
|
40
|
+
if (devBase) {
|
|
41
|
+
try {
|
|
42
|
+
const u = new URL(scheme);
|
|
43
|
+
const bundle = u.searchParams.get('bundle');
|
|
44
|
+
if (bundle && !u.searchParams.get('url')) {
|
|
45
|
+
u.searchParams.delete('bundle');
|
|
46
|
+
u.searchParams.set('url', `${devBase.replace(/\/+$/, '')}/${bundle.replace(/^(?:\.\/|\/)+/, '')}`);
|
|
47
|
+
scheme = u.toString();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (_a) {
|
|
51
|
+
// scheme is not a valid URL, pass through as-is
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
pipe.call('router.open', Object.assign({ scheme }, params.options), (v) => {
|
|
36
55
|
var _a, _b;
|
|
37
56
|
const response = v;
|
|
38
57
|
const code = (_a = response === null || response === void 0 ? void 0 : response.code) !== null && _a !== void 0 ? _a : -1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../../src/open/open.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,yEAAyE;AACzE,0DAA0D;AAC1D,OAAO,IAAI,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../../src/open/open.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,yEAAyE;AACzE,0DAA0D;AAC1D,OAAO,IAAI,MAAM,kBAAkB,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGnD;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAAC,MAAmB,EAAE,QAAwC;IAC9E,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,MAAM,aAAa,GAAiB;YAChC,IAAI,EAAE,CAAC,CAAC;YACR,GAAG,EAAE,oDAAoD;SAC5D,CAAC;QACF,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACjC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO;IACX,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/E,MAAM,aAAa,GAAiB;YAChC,IAAI,EAAE,CAAC,CAAC;YACR,GAAG,EAAE,mDAAmD;SAC3D,CAAC;QACF,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;YACjC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO;IACX,CAAC;IAED,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QACjC,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC1E,OAAO;IACX,CAAC;IAED,yEAAyE;IACzE,4CAA4C;IAC5C,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;IACtC,IAAI,OAAO,EAAE,CAAC;QACV,IAAI,CAAC;YACD,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;YAC1B,MAAM,MAAM,GAAG,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACvC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAChC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;gBACnG,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;YAC1B,CAAC;QACL,CAAC;QAAC,WAAM,CAAC;YACL,gDAAgD;QACpD,CAAC;IACL,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,aAAa,kBACnB,MAAM,IACH,MAAM,CAAC,OAAO,GAClB,CAAC,CAAU,EAAE,EAAE;;QACd,MAAM,QAAQ,GAAG,CAAiB,CAAC;QACnC,MAAM,IAAI,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,mCAAI,CAAC,CAAC,CAAC;QAClC,2EAA2E;QAC3E,0EAA0E;QAC1E,kDAAkD;QAClD,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC,CAAC;QAC7B,MAAM,GAAG,GAAG,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,GAAG,mCAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;QAClE,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;IAC5B,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"fileNames":["../../../../node_modules/.pnpm/typescript@5.
|
|
1
|
+
{"fileNames":["../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.d.ts","../../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","../src/devServer.ts","../../../sparkling-method/dist/types.d.ts","../../../sparkling-method/dist/index.d.ts","../src/close/close.d.ts","../src/close/close.ts","../src/open/open.d.ts","../src/open/open.ts","../src/navigate/navigate.d.ts","../src/navigate/navigate.ts","../index.ts","../../../../node_modules/.pnpm/@jest+expect-utils@29.7.0/node_modules/@jest/expect-utils/build/index.d.ts","../../../../node_modules/.pnpm/chalk@4.1.2/node_modules/chalk/index.d.ts","../../../../node_modules/.pnpm/@sinclair+typebox@0.27.10/node_modules/@sinclair/typebox/typebox.d.ts","../../../../node_modules/.pnpm/@jest+schemas@29.6.3/node_modules/@jest/schemas/build/index.d.ts","../../../../node_modules/.pnpm/pretty-format@29.7.0/node_modules/pretty-format/build/index.d.ts","../../../../node_modules/.pnpm/jest-diff@29.7.0/node_modules/jest-diff/build/index.d.ts","../../../../node_modules/.pnpm/jest-matcher-utils@29.7.0/node_modules/jest-matcher-utils/build/index.d.ts","../../../../node_modules/.pnpm/expect@29.7.0/node_modules/expect/build/index.d.ts","../../../../node_modules/.pnpm/@types+jest@29.5.14/node_modules/@types/jest/index.d.ts"],"fileIdsList":[[27],[29,32],[25,31],[29],[26,30],[28],[18,19,20,21,22,23],[17,18],[20],[15,21,22],[15,17,20],[16]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"4fc8c80e3f83b51aa0be32aca09faa0a00968109a8b2f9a1172999ae422f6a58","signature":"51d6a96a88f06928d2bf9400f47a225ab2ca51b0c290f5c5aeb232b04f0aca9d"},"f7633d7fe074d6a4f1d215bbc7a3b27fc0419a5a3bfbbe054ac07f3dbbc68487","bdddec6a06096ab2fc1460e59d0e8c1c954ffe72290bee32bc1ecce28ebe9393","582fe2e974682a46dcee0b08fac869d96c56ec3421ad48633f6289f497acc3fd",{"version":"437d1d1bf67ea36dbf6f48e75dc75f7385e58e91d5a0acc493cbc1cec23c59fa","signature":"f421088758adc5b04e44c1548f2d7ac1cebbdda08458c8e493a490002c8e6f7c"},"a078d8603e9ef86dbed7ba0ff50276734c4cefbc5e64a6ab07144911ff701e3b",{"version":"ad4667e00d7fce51bded3e210d1f271e651ea5516cea8ba121201bc1614e022f","signature":"dd1d64b74f46208aecdee3727641eff5c0262826752e37a19ca6b2eb474d45af"},"e3963382b8a425258f14e665e7a0d39b024f1e71b7c9200096cdc9604ddf5f94",{"version":"712aba6de5cf5a6724f0ecdc5ec1176d35e7ed1071e36fb69d696dabfb1e7088","signature":"e902e6d4f2877e301fa4cf11b50a18c6a1c078bd34edecb15ae62459310004d0"},{"version":"f4ef2dc4d2182f03365773c1c488eb01ebd07186a7d7e3c51eea5eed6c0d5252","signature":"4acdb0a03d91ac0b94410f47337f1dba8f947a74300a305e1e6a14fef3933d07"},{"version":"cdcc132f207d097d7d3aa75615ab9a2e71d6a478162dde8b67f88ea19f3e54de","impliedFormat":1},{"version":"0d14fa22c41fdc7277e6f71473b20ebc07f40f00e38875142335d5b63cdfc9d2","impliedFormat":1},{"version":"e1028394c1cf96d5d057ecc647e31e457b919092f882ed0c7092152b077fed9d","impliedFormat":1},{"version":"f315e1e65a1f80992f0509e84e4ae2df15ecd9ef73df975f7c98813b71e4c8da","impliedFormat":1},{"version":"5b9586e9b0b6322e5bfbd2c29bd3b8e21ab9d871f82346cb71020e3d84bae73e","impliedFormat":1},{"version":"3e70a7e67c2cb16f8cd49097360c0309fe9d1e3210ff9222e9dac1f8df9d4fb6","impliedFormat":1},{"version":"ab68d2a3e3e8767c3fba8f80de099a1cfc18c0de79e42cb02ae66e22dfe14a66","impliedFormat":1},{"version":"d96cc6598148bf1a98fb2e8dcf01c63a4b3558bdaec6ef35e087fd0562eb40ec","impliedFormat":1},{"version":"f8db4fea512ab759b2223b90ecbbe7dae919c02f8ce95ec03f7fb1cf757cfbeb","affectsGlobalScope":true,"impliedFormat":1}],"root":[15,19,21,23,24],"options":{"composite":true,"declaration":true,"declarationMap":true,"emitDeclarationOnly":false,"esModuleInterop":true,"module":5,"outDir":"./","skipLibCheck":true,"sourceMap":true,"strict":true,"target":2},"referencedMap":[[28,1],[33,2],[32,3],[30,4],[31,5],[29,6],[24,7],[19,8],[22,9],[23,10],[21,11],[17,12]],"latestChangedDtsFile":"./index.d.ts","version":"5.9.3"}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
require 'json'
|
|
2
|
-
|
|
3
|
-
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
|
-
|
|
5
1
|
Pod::Spec.new do |s|
|
|
6
2
|
s.name = 'Sparkling-Router'
|
|
7
|
-
s.version =
|
|
8
|
-
s.summary =
|
|
9
|
-
s.description =
|
|
10
|
-
s.license =
|
|
11
|
-
s.author =
|
|
3
|
+
s.version = "2.1.0-rc.20"
|
|
4
|
+
s.summary = "iOS navigation router SDK for Sparkling"
|
|
5
|
+
s.description = "iOS navigation router SDK for Sparkling"
|
|
6
|
+
s.license = "Apache-2.0"
|
|
7
|
+
s.author = "TikTok"
|
|
12
8
|
s.homepage = 'https://github.com/tiktok/sparkling'
|
|
13
9
|
s.platforms = {
|
|
14
10
|
:ios => '12.0'
|
|
@@ -21,7 +17,7 @@ Pod::Spec.new do |s|
|
|
|
21
17
|
'DEFINES_MODULE' => 'YES',
|
|
22
18
|
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
|
23
19
|
}
|
|
24
|
-
|
|
20
|
+
|
|
25
21
|
s.subspec 'Core' do |core|
|
|
26
22
|
core.source_files = [
|
|
27
23
|
'Sources/Core/Methods/**/*.{h,m,swift}',
|
|
@@ -29,7 +25,7 @@ Pod::Spec.new do |s|
|
|
|
29
25
|
'Sources/Core/Utils/*.{h,m,swift}',
|
|
30
26
|
]
|
|
31
27
|
end
|
|
32
|
-
|
|
28
|
+
|
|
33
29
|
s.dependency 'SparklingMethod/Core'
|
|
34
30
|
s.dependency 'SparklingMethod/DIProvider'
|
|
35
31
|
s.dependency 'Mantle', '~> 2.2.0'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sparkling-navigation",
|
|
3
|
-
"version": "2.1.0-rc.
|
|
3
|
+
"version": "2.1.0-rc.20",
|
|
4
4
|
"homepage": "https://tiktok.github.io/sparkling/",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"license": "Apache-2.0",
|
|
25
25
|
"description": "none",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"sparkling-method": "2.1.0-rc.
|
|
27
|
+
"sparkling-method": "2.1.0-rc.20"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/jest": "^29.5.12",
|
|
@@ -127,7 +127,7 @@ expect(consoleErrorSpy).toHaveBeenCalledWith('[sparkling-navigation] navigate: c
|
|
|
127
127
|
|
|
128
128
|
expect(mockOpen).toHaveBeenCalledWith(
|
|
129
129
|
{
|
|
130
|
-
scheme: 'hybrid://lynxview_page?bundle=pages%2Fsecond.lynx.bundle&title=Second
|
|
130
|
+
scheme: 'hybrid://lynxview_page?bundle=pages%2Fsecond.lynx.bundle&title=Second%20Page&screen_orientation=portrait',
|
|
131
131
|
options: { animated: true },
|
|
132
132
|
},
|
|
133
133
|
callback
|
|
@@ -213,4 +213,73 @@ expect(consoleErrorSpy).toHaveBeenCalledWith('[sparkling-navigation] navigate: c
|
|
|
213
213
|
);
|
|
214
214
|
});
|
|
215
215
|
});
|
|
216
|
+
|
|
217
|
+
describe('dev mode with globalProps', () => {
|
|
218
|
+
const savedLynx = (globalThis as any).lynx;
|
|
219
|
+
const savedDev = (globalThis as any).__DEV__;
|
|
220
|
+
const savedPublicPath = (globalThis as any).__webpack_public_path__;
|
|
221
|
+
|
|
222
|
+
beforeEach(() => {
|
|
223
|
+
(globalThis as any).__DEV__ = true;
|
|
224
|
+
(globalThis as any).__webpack_public_path__ = 'http://localhost:5969/';
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
afterEach(() => {
|
|
228
|
+
(globalThis as any).lynx = savedLynx;
|
|
229
|
+
(globalThis as any).__DEV__ = savedDev;
|
|
230
|
+
(globalThis as any).__webpack_public_path__ = savedPublicPath;
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should use base URL from globalProps.queryItems.url over __webpack_public_path__', () => {
|
|
234
|
+
(globalThis as any).lynx = {
|
|
235
|
+
__globalProps: {
|
|
236
|
+
queryItems: { url: 'http://192.168.1.100:5969/main.lynx.bundle' },
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
const callback = jest.fn();
|
|
240
|
+
|
|
241
|
+
navigate({ path: 'second.lynx.bundle' }, callback);
|
|
242
|
+
|
|
243
|
+
expect(mockOpen).toHaveBeenCalledWith(
|
|
244
|
+
expect.objectContaining({
|
|
245
|
+
scheme: expect.stringContaining('url=http%3A%2F%2F192.168.1.100%3A5969%2Fsecond.lynx.bundle'),
|
|
246
|
+
}),
|
|
247
|
+
callback,
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('should fall back to __webpack_public_path__ when globalProps has no url', () => {
|
|
252
|
+
(globalThis as any).lynx = {
|
|
253
|
+
__globalProps: { queryItems: {} },
|
|
254
|
+
};
|
|
255
|
+
const callback = jest.fn();
|
|
256
|
+
|
|
257
|
+
navigate({ path: 'second.lynx.bundle' }, callback);
|
|
258
|
+
|
|
259
|
+
expect(mockOpen).toHaveBeenCalledWith(
|
|
260
|
+
expect.objectContaining({
|
|
261
|
+
scheme: expect.stringContaining('url=http%3A%2F%2Flocalhost%3A5969%2Fsecond.lynx.bundle'),
|
|
262
|
+
}),
|
|
263
|
+
callback,
|
|
264
|
+
);
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
it('should ignore non-HTTP URLs in globalProps', () => {
|
|
268
|
+
(globalThis as any).lynx = {
|
|
269
|
+
__globalProps: {
|
|
270
|
+
queryItems: { url: 'file:///local/main.lynx.bundle' },
|
|
271
|
+
},
|
|
272
|
+
};
|
|
273
|
+
const callback = jest.fn();
|
|
274
|
+
|
|
275
|
+
navigate({ path: 'second.lynx.bundle' }, callback);
|
|
276
|
+
|
|
277
|
+
expect(mockOpen).toHaveBeenCalledWith(
|
|
278
|
+
expect.objectContaining({
|
|
279
|
+
scheme: expect.stringContaining('url=http%3A%2F%2Flocalhost%3A5969%2Fsecond.lynx.bundle'),
|
|
280
|
+
}),
|
|
281
|
+
callback,
|
|
282
|
+
);
|
|
283
|
+
});
|
|
284
|
+
});
|
|
216
285
|
});
|
package/src/devServer.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Copyright (c) 2022 TikTok Pte. Ltd.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
declare const __DEV__: boolean;
|
|
6
|
+
declare const __webpack_public_path__: string;
|
|
7
|
+
declare const lynx: { __globalProps?: { queryItems?: Record<string, string> } } | undefined;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Derive the dev server base URL from the actual bundle URL that the native
|
|
11
|
+
* side used to load this page. Falls back to __webpack_public_path__.
|
|
12
|
+
*
|
|
13
|
+
* This ensures sub-page navigation uses the same host/port that the entry
|
|
14
|
+
* page was loaded from — critical for real-device debugging where the native
|
|
15
|
+
* side may use a LAN IP while __webpack_public_path__ is baked as localhost.
|
|
16
|
+
*/
|
|
17
|
+
export function getDevServerBaseURL(): string | undefined {
|
|
18
|
+
try {
|
|
19
|
+
if (typeof __DEV__ === 'undefined' || !__DEV__) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Prefer the actual URL the native side used to load this bundle.
|
|
24
|
+
// lynx.__globalProps.queryItems.url is set by the SDK from the scheme's
|
|
25
|
+
// url= parameter (e.g. "http://192.168.1.100:5969/main.lynx.bundle").
|
|
26
|
+
if (typeof lynx !== 'undefined' && lynx?.__globalProps?.queryItems?.url) {
|
|
27
|
+
const pageUrl = lynx.__globalProps.queryItems.url;
|
|
28
|
+
if (pageUrl.startsWith('http://') || pageUrl.startsWith('https://')) {
|
|
29
|
+
const lastSlash = pageUrl.lastIndexOf('/');
|
|
30
|
+
if (lastSlash > pageUrl.indexOf('//') + 1) {
|
|
31
|
+
return pageUrl.substring(0, lastSlash + 1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Fall back to build-time value.
|
|
37
|
+
if (typeof __webpack_public_path__ === 'string' && __webpack_public_path__) {
|
|
38
|
+
return __webpack_public_path__;
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
// globals not available
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
package/src/navigate/navigate.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
3
|
// LICENSE file in the root directory of this source tree.
|
|
4
4
|
import { open } from '../open/open';
|
|
5
|
+
import { getDevServerBaseURL } from '../devServer';
|
|
5
6
|
import type {
|
|
6
7
|
NavigateRequest,
|
|
7
8
|
NavigateResponse,
|
|
@@ -9,9 +10,6 @@ import type {
|
|
|
9
10
|
NavigateParams,
|
|
10
11
|
} from './navigate.d';
|
|
11
12
|
|
|
12
|
-
declare const __DEV__: boolean;
|
|
13
|
-
declare const __webpack_public_path__: string;
|
|
14
|
-
|
|
15
13
|
const DEFAULT_ROUTER_SCHEME = 'hybrid://lynxview_page';
|
|
16
14
|
const PROTOCOL_REGEX = /^[a-z][a-z0-9+.-]*:\/\//i;
|
|
17
15
|
|
|
@@ -29,17 +27,6 @@ function normalizePath(path: string): string {
|
|
|
29
27
|
return normalized;
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
function getDevServerBaseURL(): string | undefined {
|
|
33
|
-
try {
|
|
34
|
-
if (typeof __DEV__ !== 'undefined' && __DEV__ && typeof __webpack_public_path__ === 'string' && __webpack_public_path__) {
|
|
35
|
-
return __webpack_public_path__;
|
|
36
|
-
}
|
|
37
|
-
} catch {
|
|
38
|
-
// __DEV__ or __webpack_public_path__ not available
|
|
39
|
-
}
|
|
40
|
-
return undefined;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
30
|
function buildScheme(baseScheme: string, bundlePath: string, params?: NavigateOptions['params']): string {
|
|
44
31
|
const sanitizedBase = (baseScheme || DEFAULT_ROUTER_SCHEME).trim().replace(/[?&]+$/, '') || DEFAULT_ROUTER_SCHEME;
|
|
45
32
|
const searchParams = new URLSearchParams();
|
|
@@ -73,7 +60,9 @@ function buildScheme(baseScheme: string, bundlePath: string, params?: NavigateOp
|
|
|
73
60
|
}
|
|
74
61
|
}
|
|
75
62
|
|
|
76
|
-
|
|
63
|
+
// URLSearchParams encodes spaces as '+' (x-www-form-urlencoded), but
|
|
64
|
+
// native URL parsers only understand '%20'. Replace to avoid mangled values.
|
|
65
|
+
return `${sanitizedBase}?${searchParams.toString().replace(/\+/g, '%20')}`;
|
|
77
66
|
}
|
|
78
67
|
|
|
79
68
|
export function navigate(params: NavigateRequest, callback: (result: NavigateResponse) => void): void {
|
package/src/open/open.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
3
|
// LICENSE file in the root directory of this source tree.
|
|
4
4
|
import pipe from 'sparkling-method';
|
|
5
|
+
import { getDevServerBaseURL } from '../devServer';
|
|
5
6
|
import type { OpenRequest, OpenResponse } from './open.d';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -37,8 +38,26 @@ export function open(params: OpenRequest, callback: (result: OpenResponse) => vo
|
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
// In dev mode, rewrite bundle= to url= so the native side loads from the
|
|
42
|
+
// dev server instead of stale local assets.
|
|
43
|
+
let scheme = params.scheme.trim();
|
|
44
|
+
const devBase = getDevServerBaseURL();
|
|
45
|
+
if (devBase) {
|
|
46
|
+
try {
|
|
47
|
+
const u = new URL(scheme);
|
|
48
|
+
const bundle = u.searchParams.get('bundle');
|
|
49
|
+
if (bundle && !u.searchParams.get('url')) {
|
|
50
|
+
u.searchParams.delete('bundle');
|
|
51
|
+
u.searchParams.set('url', `${devBase.replace(/\/+$/, '')}/${bundle.replace(/^(?:\.\/|\/)+/, '')}`);
|
|
52
|
+
scheme = u.toString();
|
|
53
|
+
}
|
|
54
|
+
} catch {
|
|
55
|
+
// scheme is not a valid URL, pass through as-is
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
40
59
|
pipe.call('router.open', {
|
|
41
|
-
scheme
|
|
60
|
+
scheme,
|
|
42
61
|
...params.options,
|
|
43
62
|
}, (v: unknown) => {
|
|
44
63
|
const response = v as OpenResponse;
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
// Copyright 2025 The Sparkling Authors. All rights reserved.
|
|
2
|
-
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
-
// LICENSE file in the root directory of this source tree.
|
|
4
|
-
|
|
5
|
-
import XCTest
|
|
6
|
-
import SparklingMethod
|
|
7
|
-
import SparklingMethodRouter
|
|
8
|
-
|
|
9
|
-
class SPKRouterTest: XCTestCase {
|
|
10
|
-
|
|
11
|
-
// MARK: - CloseMethod Tests
|
|
12
|
-
|
|
13
|
-
func testCloseMethodName() {
|
|
14
|
-
let method = CloseMethod()
|
|
15
|
-
XCTAssertEqual(method.methodName, "router.close")
|
|
16
|
-
XCTAssertEqual(CloseMethod.methodName(), "router.close")
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
func testCloseMethodModels() {
|
|
20
|
-
let method = CloseMethod()
|
|
21
|
-
XCTAssertTrue(method.paramsModelClass is CloseMethodParamModel.Type)
|
|
22
|
-
XCTAssertTrue(method.resultModelClass is EmptyMethodModelClass.Type)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
func testCloseMethodParamModelValidation() {
|
|
26
|
-
let paramModel = CloseMethodParamModel()
|
|
27
|
-
|
|
28
|
-
// Test without required field
|
|
29
|
-
XCTAssertThrowsError(try paramModel.validate())
|
|
30
|
-
|
|
31
|
-
// Test with required field
|
|
32
|
-
paramModel.containerID = "test-container"
|
|
33
|
-
XCTAssertNoThrow(try paramModel.validate())
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
func testCloseMethodParamModelJSONMapping() {
|
|
37
|
-
let paramModel = CloseMethodParamModel()
|
|
38
|
-
paramModel.containerID = "test-container"
|
|
39
|
-
paramModel.animated = true
|
|
40
|
-
|
|
41
|
-
XCTAssertEqual(paramModel.jsonKeyPathsByPropertyKey() as? [String: String], [
|
|
42
|
-
"containerID": "containerID",
|
|
43
|
-
"animated": "animated"
|
|
44
|
-
])
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// MARK: - OpenMethod Tests
|
|
48
|
-
|
|
49
|
-
func testOpenMethodName() {
|
|
50
|
-
let method = OpenMethod()
|
|
51
|
-
XCTAssertEqual(method.methodName, "router.open")
|
|
52
|
-
XCTAssertEqual(OpenMethod.methodName(), "router.open")
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
func testOpenMethodModels() {
|
|
56
|
-
let method = OpenMethod()
|
|
57
|
-
XCTAssertTrue(method.paramsModelClass is OpenMethodParamModel.Type)
|
|
58
|
-
XCTAssertTrue(method.resultModelClass is EmptyMethodModelClass.Type)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
func testOpenMethodParamModelValidation() {
|
|
62
|
-
let paramModel = OpenMethodParamModel()
|
|
63
|
-
|
|
64
|
-
// Test without required field
|
|
65
|
-
XCTAssertThrowsError(try paramModel.validate())
|
|
66
|
-
|
|
67
|
-
// Test with required field
|
|
68
|
-
paramModel.scheme = "https://example.com"
|
|
69
|
-
XCTAssertNoThrow(try paramModel.validate())
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
func testOpenMethodParamModelJSONMapping() {
|
|
73
|
-
let paramModel = OpenMethodParamModel()
|
|
74
|
-
|
|
75
|
-
XCTAssertEqual(paramModel.jsonKeyPathsByPropertyKey() as? [String: String], [
|
|
76
|
-
"scheme": "scheme",
|
|
77
|
-
"replace": "replace",
|
|
78
|
-
"replaceType": "replaceType",
|
|
79
|
-
"useSysBrowser": "useSysBrowser",
|
|
80
|
-
"animated": "animated",
|
|
81
|
-
"interceptor": "interceptor",
|
|
82
|
-
"extra": "extra"
|
|
83
|
-
])
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
func testOpenMethodParamModelDefaultValues() {
|
|
87
|
-
let paramModel = OpenMethodParamModel()
|
|
88
|
-
paramModel.scheme = "test-scheme"
|
|
89
|
-
|
|
90
|
-
XCTAssertFalse(paramModel.replace)
|
|
91
|
-
XCTAssertFalse(paramModel.useSysBrowser)
|
|
92
|
-
XCTAssertFalse(paramModel.animated)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
func testOpenMethodParamModelAllFields() {
|
|
96
|
-
let paramModel = OpenMethodParamModel()
|
|
97
|
-
paramModel.scheme = "test-scheme"
|
|
98
|
-
paramModel.replace = true
|
|
99
|
-
paramModel.replaceType = "all"
|
|
100
|
-
paramModel.useSysBrowser = true
|
|
101
|
-
paramModel.animated = true
|
|
102
|
-
paramModel.interceptor = "test-interceptor"
|
|
103
|
-
let extraDict = NSDictionary(dictionary: ["key": "value"])
|
|
104
|
-
paramModel.extra = extraDict
|
|
105
|
-
|
|
106
|
-
XCTAssertEqual(paramModel.scheme, "test-scheme")
|
|
107
|
-
XCTAssertTrue(paramModel.replace)
|
|
108
|
-
XCTAssertEqual(paramModel.replaceType, "all")
|
|
109
|
-
XCTAssertTrue(paramModel.useSysBrowser)
|
|
110
|
-
XCTAssertTrue(paramModel.animated)
|
|
111
|
-
XCTAssertEqual(paramModel.interceptor, "test-interceptor")
|
|
112
|
-
XCTAssertEqual(paramModel.extra, extraDict)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
func testOpenMethodParamModelFromDictParsesExtraObject() throws {
|
|
116
|
-
let dict: [String: Any] = [
|
|
117
|
-
"scheme": "hybrid://lynxview_page?bundle=a.lynx.bundle",
|
|
118
|
-
"extra": ["foo": "bar"],
|
|
119
|
-
]
|
|
120
|
-
let model = try XCTUnwrap(try OpenMethodParamModel.from(dict: dict))
|
|
121
|
-
XCTAssertNotNil(model.extra)
|
|
122
|
-
XCTAssertEqual(model.extra?["foo"] as? String, "bar")
|
|
123
|
-
}
|
|
124
|
-
}
|