/* * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * * Copyright 2022 Metrological * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { expectType, expectAssignable, expectNotAssignable, expectDeprecated, expectNotDeprecated } from 'tsd'; import { Router, Lightning } from '../../index.js' import Request from '../../src/Router/model/Request.js'; function Router_Config_Tests() { /// Basic expectAssignable({ root: 'splash', routes: [ { path: 'splash', component: {} as Router.PageConstructor }, {} as Router.RouteDefinition, {} as Router.RouteDefinition ] }); /// `root` and `routes` are required! expectNotAssignable({ root: 'splash', }); expectNotAssignable({ routes: [], }); /// `root` and `routes` type sanity check expectNotAssignable({ root: 123, // Must be a string! routes: [ {} as Router.RouteDefinition ] }); expectNotAssignable({ root: 'abc', routes: [ {} // Must be RouteDefinition! ] }); /// `boot` and `root` as promise returning callbacks expectAssignable({ root: () => { return Promise.resolve('splash') }, boot: (qs) => { /// `qs` infers to param type expectType>(qs); return Promise.resolve(); }, routes: [] }); /// Supports custom `appInstance` any component expectAssignable({ root: 'splash', routes: [], appInstance: {} as Lightning.Component }); /// `updateHash` expectAssignable({ root: 'splash', routes: [], updateHash: false }); /// `beforeEachRoute` expectAssignable({ root: 'splash', routes: [], beforeEachRoute: async (from, to) => { expectType(from); expectType(to); return true; } }); /// `afterEachRoute` expectAssignable({ root: 'splash', routes: [], afterEachRoute: (request) => { expectType(request); return true; } }); /// `bootComponent` deprecated const routeConfig = {} as Router.Config; expectDeprecated(routeConfig.bootComponent); } function Router_startRouter_Tests() { const routeConfig = {} as Router.Config; /// Supports just passing a `config` expectType(Router.startRouter(routeConfig)); // @ts-expect-error `config` can't be a number Router.startRouter(123); /// Supports passing a `config` and an app `instance` expectType(Router.startRouter(routeConfig, {} as Lightning.Component)); // @ts-expect-error `instance` can't be a number Router.startRouter(routeConfig, 123); } function Router_RouteDefinition_Tests() { class MyPage extends Lightning.Component {} /// Simple RouteDefintions can be assigned expectAssignable({ path: 'myPath/:param1/:param2', component: MyPage }); /// Non-Pages cannot be assigned expectNotAssignable({ path: 'myPath/:param1/:param2', component: Lightning.components.ListComponent }); /// Non-Pages can be assigned with `any` expectAssignable({ path: 'myPath/:param1/:param2', component: Lightning.components.ListComponent as any }); /// Can assign `on` expectAssignable({ path: 'myPath/:param1/:param2', component: MyPage, async on(page, { param1, param2 }) { expectType(page); expectAssignable(page); expectType(param1); expectType(param2); } }); /// Can assign `before` expectAssignable({ path: 'myPath/:param1/:param2', component: MyPage, async before(page, { param1, param2 }) { expectType(page); expectAssignable(page); expectType(param1); expectType(param2); } }); /// Can assign `after` expectAssignable({ path: 'myPath/:param1/:param2', component: MyPage, async after(page, { param1, param2 }) { expectType(page); expectAssignable(page); expectType(param1); expectType(param2); } }); /// Can assign `cache` expectAssignable({ path: 'myPath/:param1/:param2', component: MyPage, cache: 1000 }); /// Can assign `widgets` expectAssignable({ path: 'myPath/:param1/:param2', component: MyPage, widgets: ['anotherwidget', 'myclockwidget', 'mymenuwidget', 'mywidget'] }); } function Router_navigate_Tests() { // Many examples taken from documentation: // https://lightningjs.io/docs/#/lightning-sdk-reference/plugins/router/navigation?id=router-navigation const namedNavigatePath: Router.NamedNavigationPath = {} as Router.NamedNavigationPath; const navigateArgs: Router.NavigateArgs = {} as Router.NavigateArgs; /// Can do simple navigate by string or named route expectType( Router.navigate('player/1638') ); expectType( Router.navigate(namedNavigatePath) ); /// Can do navigate with args expectType( Router.navigate('player/1638', navigateArgs) ); expectType( Router.navigate(namedNavigatePath, navigateArgs) ); /// Can do navigate and set 2nd param to false (to prevent history) expectType( Router.navigate('player/1638', false) ); expectType( Router.navigate(namedNavigatePath, false) ); /// Can do navigate and set 3rd param to false (to prevent history) expectType( Router.navigate('player/1638', navigateArgs, false) ); expectType( Router.navigate(namedNavigatePath, navigateArgs, false) ); } function Router_NamedNavigationPath_Tests() { /// `to` is the mimimum property required expectAssignable({ to: 'player', }); expectNotAssignable({}); /// Allow `params` to be specified expectAssignable({ to: 'player', params: { unknownProp1: 123, unknownProp2: 'abc', unknownProp3: true, } }); /// As well as `query` expectAssignable({ to: 'player', params: { unknownProp1: 123, unknownProp2: 'abc', unknownProp3: true, }, query: { unknownProp1: 123, unknownProp2: 'abc', unknownProp3: true, } }); /// `params` must be a Record (if defined) expectNotAssignable({ to: 'player', params: { unknownProp4: {} // Not allowed } }); expectType | undefined>({} as Router.NamedNavigationPath['params']); /// `query` must be a Record (if defined) expectNotAssignable({ to: 'player', query: { unknownProp4: {} // Not allowed } }); expectType | undefined>({} as Router.NamedNavigationPath['params']); } function Router_NavigateArgs_Tests() { /// NavigateArgs allows keepAlive, reload and anything else. expectAssignable({ keepAlive: true, reload: true, unknownProp1: 'abc', unknownProp2: 123, unknownProp3: false, unknownProp4: {} }); /// NavigateArgs: keepAlive and reload must be booleans expectType({} as Router.NavigateArgs['keepAlive']); expectNotAssignable({ keepAlive: 'string', }); expectType({} as Router.NavigateArgs['reload']); expectNotAssignable({ reload: 'string', }); } function Router_resume_Tests() { /// Should return void with no params expectType(Router.resume()); /// Should error if there are any params // @ts-expect-error Router.resume('abc'); } function Router_step_Tests() { /// `step` is an alias of `go` expectType(Router.step); /// Should be deprecated expectDeprecated(Router.step); } function Router_go_Tests() { /// Works with no parameters expectType(Router.go()); /// Works with numeric parameters expectType(Router.go(-1)); expectType(Router.go(-2)); expectType(Router.go(-3)); /// Should not be deprecated expectNotDeprecated(Router.go); } function Router_back_Tests() { /// back() can be called with no parameters expectType(Router.back()); } function Router_activePage_Tests() { /// Returns the correct value but is deprecated expectType(Router.activePage()); /// Should be deprecated expectDeprecated(Router.activePage); } function Router_getActivePage_Tests() { /// Returns the correct value and is not deprecated expectType(Router.getActivePage()); /// Should not be deprecated expectNotDeprecated(Router.getActivePage); } function Router_getActiveRoute_Tests() { /// Returns the correct value and is not deprecated expectType(Router.getActiveRoute()); } function Router_getActiveHash_Tests() { /// Returns the correct value and is not deprecated expectType(Router.getActiveHash()); } declare module '../../index.js' { namespace Router { interface CustomWidgets { MyWidget: Lightning.Component AnotherWidget: Lightning.Component } } } function Router_focusWidget_Tests() { /// Works with augmented `CustomWidgets` expectType(Router.focusWidget('MyWidget')); expectType(Router.focusWidget('AnotherWidget')); /// Unknown widgets error (including lowercase forms of known widgets) // @ts-expect-error Router.focusWidget('mywidget'); // @ts-expect-error Router.focusWidget('UnknownWidget'); } function Router_getActiveWidget_Tests() { /// Returns the right value expectType(Router.getActiveWidget()); /// Param sanity check: Should not accept a parameter // @ts-expect-error Router.getActiveWidget(123); } function Router_restoreFocus_Tests() { /// Should be an alias of focusPage expectType(Router.focusPage); /// Should be deprecated expectDeprecated(Router.restoreFocus); } function Router_focusPage_Tests() { /// Should return void and accept no params expectType(Router.focusPage()); /// Param sanity check: Should not accept a parameter // @ts-expect-error Router.getActiveWidget(123); /// Should not be deprecated expectNotDeprecated(Router.focusPage); } function Router_isNavigating_Tests() { /// Works as expected expectType(Router.isNavigating()); } function Router_getHistory_Tests() { /// Should return an array of HistoryEntry[] expectType(Router.getHistory()); } function Router_setHistory_Tests() { /// Should return void, accepts an array of history objects expectType(Router.setHistory([{ hash: '', state: {} }, { hash: '', state: {} }])); /// Should error if first param is not an array or if less than or more than one param is provided // @ts-expect-error Router.setHistory(123); // @ts-expect-error Router.setHistory(); // @ts-expect-error Router.setHistory([], 'abc'); } function Router_HistoryState_Tests() { type HistState = { myParam1: number, myParam2: string }; interface CustomTypeConfig extends Lightning.Component.TypeConfig { HistoryStateType: HistState } /// Should be typed as `Record | null | undefined` if no params are passed to it expectType | null | undefined>({} as Router.HistoryState); /// Should extract the `HistoryStateType` if a TypeConfig is passed expectType({} as Router.HistoryState); /// Otherwise, it should just pass through any other object type passed in expectType({} as Router.HistoryState); } function Router_getHistoryState_Tests() { /// Should return HistoryState | null, and accept an optional `hash` string expectType(Router.getHistoryState()); expectType(Router.getHistoryState('abc')); /// Should error if first param isn't a string of if more than 1 param is provided // @ts-expect-error Router.getHistoryState(123); // @ts-expect-error Router.getHistoryState('abc', 123); } function Router_replaceHistoryState_Tests() { /// Should return void and work with no params, 1 param or 2 params expectType(Router.replaceHistoryState()); expectType(Router.replaceHistoryState({} as Router.HistoryState)); expectType(Router.replaceHistoryState(null)); expectType(Router.replaceHistoryState({} as Router.HistoryState, 'hash')); /// Should error if params are of wrong type or more than 2 // @ts-expect-error Router.replaceHistoryState(123); // @ts-expect-error Router.replaceHistoryState(null, 123); // @ts-expect-error Router.replaceHistoryState(null, 'hash', 'abc'); } function Router_getQueryStringParams_Tests() { /// Should return correct type and work with no params or 1 param expectType(Router.getQueryStringParams()); expectType(Router.getQueryStringParams('hash')); /// Should error if there are more than 1 param or type of param is incorrect // @ts-expect-error Router.getQueryStringParams(false); // @ts-expect-error Router.getQueryStringParams('hash', false); } function Router_reload_Tests() { /// Should return void with no params expectType(Router.reload()); /// Should error if there are any params // @ts-expect-error Router.reload('abc'); } function Router_root_Tests() { /// Should return void with no params expectType(Router.root()); /// Should error if there are any params // @ts-expect-error Router.root('abc'); }