Skip to content

Commit

Permalink
fix: various path navigation issues (#1190)
Browse files Browse the repository at this point in the history
* fix: various path navigation issues

sdk selection was broken on the developer portal because some scenes weren't using the react dom `location` for `location.pathname`

* update yarn-deduplicate

* WIP fixing some tests

added funSDK syntax for TypeScript `makeTheCall()`

* fix location mock in tests
  • Loading branch information
jkaster authored Oct 17, 2022
1 parent 7ee39bb commit e73da3d
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 43 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@
"webpack": "^5.10.0",
"webpack-bundle-analyzer": "^4.4.1",
"webpack-merge": "^5.7.3",
"yarn-deduplicate": "^3.1.0"
"yarn-deduplicate": "^6.0.0"
},
"dependencies": {},
"lint-staged": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type { FC } from 'react'
import React, { useEffect, useState } from 'react'
import { Select } from '@looker/components'
import { useSelector } from 'react-redux'
import { useLocation } from 'react-router-dom'
import { selectSdkLanguage } from '../../state'
import { allAlias, useNavigation } from '../../utils'
import { allSdkLanguageOptions } from './utils'
Expand All @@ -35,6 +36,7 @@ import { allSdkLanguageOptions } from './utils'
* Allows the user to select their preferred SDK language
*/
export const SdkLanguageSelector: FC = () => {
const location = useLocation()
const { navigate } = useNavigation()
const selectedSdkLanguage = useSelector(selectSdkLanguage)
const [language, setLanguage] = useState(selectedSdkLanguage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export const MethodScene: FC<MethodSceneProps> = ({ api }) => {
}, [adaptor, setOn])

useEffect(() => {
if (method.responses && errorCode) {
if (method?.responses && errorCode) {
if (docResponsesRef.current) {
window.setTimeout(() => {
docResponsesRef.current!.scrollIntoView()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ jest.mock('react-router-dom', () => {
...ReactRouterDOM,
useHistory: () => ({
push: mockHistoryPush,
location,
location: {
pathname: '/4.0/methods/Look',
},
}),
}
})
Expand All @@ -54,7 +56,7 @@ describe('MethodTagScene', () => {
<Route path="/:specKey/methods/:methodTag">
<MethodTagScene api={api} />
</Route>,
['/3.1/methods/ColorCollection']
['/4.0/methods/ColorCollection']
)
expect(
screen.getAllByRole('button', {
Expand All @@ -68,7 +70,7 @@ describe('MethodTagScene', () => {
screen.getByText('/color_collections/standard').closest('a')
).toHaveAttribute(
'href',
'/3.1/methods/ColorCollection/color_collections_standard'
'/4.0/methods/ColorCollection/color_collections_standard'
)
})

Expand All @@ -78,7 +80,7 @@ describe('MethodTagScene', () => {
<Route path="/:specKey/methods/:methodTag">
<MethodTagScene api={api} />
</Route>,
['/3.1/methods/ApiAuth']
['/4.0/methods/ApiAuth']
)
expect(
screen.getAllByRole('button', {
Expand All @@ -88,17 +90,18 @@ describe('MethodTagScene', () => {
})

test('it pushes filter to URL on toggle', async () => {
const site = '/4.0/methods/Look'
renderWithRouterAndReduxProvider(
<Route path="/:specKey/methods/:methodTag">
<MethodTagScene api={api} />
</Route>,
['/3.1/methods/Look']
[site]
)
/** Filter by GET operation */
userEvent.click(screen.getByRole('button', { name: 'GET' }))
await waitFor(() => {
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: location.pathname,
pathname: site,
search: 't=get',
})
})
Expand All @@ -107,7 +110,7 @@ describe('MethodTagScene', () => {
await waitFor(() => {
// eslint-disable-next-line jest-dom/prefer-in-document
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: location.pathname,
pathname: site,
search: 't=delete',
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
*/
import type { FC } from 'react'
import React, { useEffect, useState } from 'react'
import { useHistory, useParams } from 'react-router-dom'
import { useHistory, useLocation, useParams } from 'react-router-dom'
import { Grid, ButtonToggle, ButtonItem } from '@looker/components'
import type { ApiModel } from '@looker/sdk-codegen'
import { useSelector } from 'react-redux'
Expand All @@ -46,6 +46,7 @@ interface MethodTagSceneParams {

export const MethodTagScene: FC<MethodTagSceneProps> = ({ api }) => {
const { specKey, methodTag } = useParams<MethodTagSceneParams>()
const location = useLocation()
const history = useHistory()
const methods = api.tags[methodTag]
const { navigate, buildPathWithGlobalParams, navigateWithGlobalParams } =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,33 @@ import { TypeTagScene } from './TypeTagScene'
const opBtnNames = /ALL|SPECIFICATION|WRITE|REQUEST|ENUMERATED/

const path = '/:specKey/types/:typeTag'

const mockHistoryPush = jest.fn()
jest.mock('react-router-dom', () => {
const ReactRouterDOM = jest.requireActual('react-router-dom')
return {
...ReactRouterDOM,
useLocation: () => ({
pathname: '/4.0/types/Look',
}),
useHistory: () => ({
push: mockHistoryPush,
location,
location: {
pathname: '/4.0/types/Look',
},
}),
}
})

describe('TypeTagScene', () => {
Element.prototype.scrollTo = jest.fn()
// const mockHistoryPush: jest.Mock = useHistory as jest.Mock

test('it renders type buttons and all methods for a given type tag', () => {
renderWithRouterAndReduxProvider(
<Route path={path}>
<TypeTagScene api={api} />
</Route>,
['/3.1/types/Dashboard']
['/4.0/types/Dashboard']
)
expect(
screen.getAllByRole('button', {
Expand All @@ -68,7 +73,7 @@ describe('TypeTagScene', () => {
)
expect(screen.getByText('DashboardBase').closest('a')).toHaveAttribute(
'href',
'/3.1/types/Dashboard/DashboardBase'
'/4.0/types/Dashboard/DashboardBase'
)
})

Expand All @@ -77,7 +82,7 @@ describe('TypeTagScene', () => {
<Route path={path}>
<TypeTagScene api={api} />
</Route>,
['/3.1/types/DataAction']
['/4.0/types/DataAction']
)
expect(
screen.getAllByRole('button', {
Expand All @@ -87,25 +92,26 @@ describe('TypeTagScene', () => {
})

test('it pushes filter to URL on toggle', async () => {
const site = '/4.0/types/Look'
renderWithRouterAndReduxProvider(
<Route path={path}>
<TypeTagScene api={api} />
</Route>,
['/3.1/types/Look']
[site]
)
/** Filter by SPECIFICATION */
userEvent.click(screen.getByRole('button', { name: 'SPECIFICATION' }))
await waitFor(() => {
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: location.pathname,
pathname: site,
search: 't=specification',
})
})
/** Filter by REQUEST */
userEvent.click(screen.getByRole('button', { name: 'REQUEST' }))
await waitFor(() => {
expect(mockHistoryPush).toHaveBeenCalledWith({
pathname: location.pathname,
pathname: site,
search: 't=request',
})
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import type { FC } from 'react'
import React, { useEffect, useState } from 'react'
import { Grid, ButtonToggle, ButtonItem } from '@looker/components'
import type { ApiModel } from '@looker/sdk-codegen'
import { useParams } from 'react-router-dom'
import { useLocation, useParams } from 'react-router-dom'
import { useSelector } from 'react-redux'
import { ApixSection, DocTitle, DocTypeSummary, Link } from '../../components'
import { buildTypePath, isValidFilter, useNavigation } from '../../utils'
Expand All @@ -46,6 +46,7 @@ interface TypeTagSceneParams {

export const TypeTagScene: FC<TypeTagSceneProps> = ({ api }) => {
const { specKey, typeTag } = useParams<TypeTagSceneParams>()
const location = useLocation()
const { navigate, buildPathWithGlobalParams, navigateWithGlobalParams } =
useNavigation()
const selectedTagFilter = useSelector(selectTagFilter)
Expand Down
109 changes: 100 additions & 9 deletions packages/sdk-codegen/src/typescript.gen.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,23 +174,33 @@ describe('typescript generator', () => {
const inputs = {}
const method = apiTestModel.methods.run_look
const actual = gen.makeTheCall(method, inputs)
const expected = 'let response = await sdk.ok(sdk.run_look())'
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(run_look(sdk))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.run_look())`
expect(actual).toEqual(expected)
})

it('assigns single param', () => {
const inputs = { look_id: 17 }
const method = apiTestModel.methods.look
const actual = gen.makeTheCall(method, inputs)
const expected = `let response = await sdk.ok(sdk.look(17))`
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(look(sdk,17))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.look(17))`
expect(actual).toEqual(expected)
})

it('assigns simple params', () => {
const inputs = { look_id: 17, fields }
const method = apiTestModel.methods.look
const actual = gen.makeTheCall(method, inputs)
const expected = `let response = await sdk.ok(sdk.look(
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(look(sdk,
17, '${fields}'))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.look(
17, '${fields}'))`
expect(actual).toEqual(expected)
})
Expand All @@ -208,7 +218,19 @@ describe('typescript generator', () => {
const inputs = { look_id: 17, body, fields }
const method = apiTestModel.methods.update_look
const actual = gen.makeTheCall(method, inputs)
const expected = `let response = await sdk.ok(sdk.update_look(
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(update_look(sdk,
17, {
title: 'test title',
description: 'gen test',
query: {
model: 'the_look',
view: 'users',
total: true
}
}, 'id,user_id,title,description'))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.update_look(
17, {
title: 'test title',
description: 'gen test',
Expand All @@ -225,7 +247,14 @@ describe('typescript generator', () => {
const inputs = { look_id: 17, result_format: 'png' }
const method = apiTestModel.methods.run_look
const actual = gen.makeTheCall(method, inputs)
const expected = `let response = await sdk.ok(sdk.run_look(
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(run_look(sdk,
{
look_id: 17,
result_format: 'png'
}))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.run_look(
{
look_id: 17,
result_format: 'png'
Expand All @@ -242,7 +271,16 @@ describe('typescript generator', () => {
}
const method = apiTestModel.methods.create_query_task
const actual = gen.makeTheCall(method, inputs)
const expected = `let response = await sdk.ok(sdk.create_query_task(
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(create_query_task(sdk,
{
body: {
query_id: 1,
result_format: ResultFormat.csv
}
}))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.create_query_task(
{
body: {
query_id: 1,
Expand All @@ -258,7 +296,13 @@ describe('typescript generator', () => {
}
const method = apiTestModel.methods.all_users
const actual = gen.makeTheCall(method, inputs)
const expected = `let response = await sdk.ok(sdk.all_users(
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(all_users(sdk,
{
ids: new DelimArray<number>([1,2,3])
}))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.all_users(
{
ids: new DelimArray<number>([1,2,3])
}))`
Expand Down Expand Up @@ -295,7 +339,43 @@ describe('typescript generator', () => {
const inputs = { body, fields }
const method = apiTestModel.methods.create_merge_query
const actual = gen.makeTheCall(method, inputs)
const expected = `let response = await sdk.ok(sdk.create_merge_query(
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(create_merge_query(sdk,
{
body: {
pivots: [
'one',
'two',
'three'
],
sorts: ['a'],
source_queries: [
{
merge_fields: [
{
field_name: 'merge_1',
source_field_name: 'source_1'
}
],
name: 'first query',
query_id: 1
},
{
merge_fields: [
{
field_name: 'merge_2',
source_field_name: 'source_2'
}
],
name: 'second query',
query_id: 2
}
]
},
fields: 'id,user_id,title,description'
}))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.create_merge_query(
{
body: {
pivots: [
Expand Down Expand Up @@ -340,7 +420,18 @@ describe('typescript generator', () => {
}
const inputs = { body: query }
const method = apiTestModel.methods.create_sql_query
const expected = `let response = await sdk.ok(sdk.create_sql_query(
const expected = `// functional SDK syntax is recommended for minimizing browser payloads
let response = await sdk.ok(create_sql_query(sdk,
{
connection_name: 'looker',
model_name: 'the_look',
vis_config: {
first: 1,
second: 'two'
}
}))
// monolithic SDK syntax can also be used for Node apps
let response = await sdk.ok(sdk.create_sql_query(
{
connection_name: 'looker',
model_name: 'the_look',
Expand Down
Loading

0 comments on commit e73da3d

Please sign in to comment.