Skip to content

Commit

Permalink
Fix tests (googleanalytics#716)
Browse files Browse the repository at this point in the history
* cleaned up how fakes are set up.

* got very basic stream picker test working.

* fixed ua dims-mets tests

* fixed account explorer tests.

* fixed viewselector tests.

* fixed campaign url builder tests.
  • Loading branch information
diminishedprime committed Sep 2, 2021
1 parent 0d3deaa commit a1acac2
Show file tree
Hide file tree
Showing 16 changed files with 368 additions and 390 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
"react-test-renderer": "^17.0.2",
"ts-node": "^9.1.1",
"tsconfig-paths-webpack-plugin": "^3.5.1",
"type-fest": "^2.1.0",
"typescript": "^4.2.4"
},
"resolutions": {
Expand Down
36 changes: 14 additions & 22 deletions src/components/AccountExplorer/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,38 @@

import * as React from "react"
import * as renderer from "@testing-library/react"
import { withProviders, testGapi } from "../../test-utils"
import { withProviders } from "../../test-utils"
import "@testing-library/jest-dom"

import AccountExplorer from "./index"

describe("AccountExplorer", () => {
it("renders without error for an unauthorized user", async () => {
const { wrapped, store } = withProviders(<AccountExplorer />)
store.dispatch({ type: "setUser", user: undefined })
const { findByTestId } = renderer.render(wrapped)
const result = await findByTestId("components/ViewTable/no-results")
expect(result).toBeVisible()
const { wrapped } = withProviders(<AccountExplorer />, {
isLoggedIn: false,
})
const { findByText } = renderer.render(wrapped)

const heading = await findByText("Overview")
expect(heading).toBeVisible()
})
describe("with an authorized user", () => {
const user = { getId: () => "userId" }
describe("with accounts", () => {
it("selects the first account & shows it in the tree", async () => {
const gapi = testGapi()
const { wrapped, store } = withProviders(<AccountExplorer />)
store.dispatch({ type: "setUser", user })
store.dispatch({ type: "setGapi", gapi })
const { wrapped, gapi } = withProviders(<AccountExplorer />)
const { findByText } = renderer.render(wrapped)
await renderer.act(async () => {
await gapi.client.analytics.management.accountSummaries.list()
await gapi!.client!.analytics!.management!.accountSummaries!.list!()
})
const viewColumn = await findByText("View Name 1 1 1")
expect(viewColumn).toBeVisible()
})
it("picking a view updates the table", async () => {
const gapi = testGapi()
const { wrapped, store } = withProviders(<AccountExplorer />)
store.dispatch({ type: "setUser", user })
store.dispatch({ type: "setGapi", gapi })
const { wrapped, gapi } = withProviders(<AccountExplorer />)

const { findByText, findByLabelText } = renderer.render(wrapped)
await renderer.act(async () => {
await gapi.client.analytics.management.accountSummaries.list()
await gapi!.client!.analytics!.management!.accountSummaries!.list!()
})
await renderer.act(async () => {
// Choose the second view in the list
Expand All @@ -63,14 +58,11 @@ describe("AccountExplorer", () => {
expect(viewColumn).toBeVisible()
})
it("searching for a view updates the table", async () => {
const gapi = testGapi()
const { wrapped, store } = withProviders(<AccountExplorer />)
store.dispatch({ type: "setUser", user })
store.dispatch({ type: "setGapi", gapi })
const { wrapped, gapi } = withProviders(<AccountExplorer />)

const { findByText, findByPlaceholderText } = renderer.render(wrapped)
await renderer.act(async () => {
await gapi.client.analytics.management.accountSummaries.list()
await gapi!.client!.analytics!.management!.accountSummaries!.list!()
})
await renderer.act(async () => {
// Choose the second view in the list
Expand Down
4 changes: 2 additions & 2 deletions src/components/CampaignURLBuilder/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ describe("for the Campaign URL Builder component", () => {
})
})
describe("entering a no-no url shows a warning", () => {
test("url: ga-dev-tools.appspot.com", async () => {
test("url: ga-dev-tools.web.app", async () => {
const { wrapped } = withProviders(
<CampaignURLBuilder
version={GAVersion.UniversalAnalytics}
Expand All @@ -95,7 +95,7 @@ describe("for the Campaign URL Builder component", () => {
const { findByLabelText: find, findByTestId } = renderer.render(wrapped)
await userEvent.type(
await find(/website URL/),
"https://ga-dev-tools.appspot.com"
"https://ga-dev-tools.web.app"
)

const warningBanner = await findByTestId("bad-url-warnings")
Expand Down
2 changes: 1 addition & 1 deletion src/components/DimensionsMetricsExplorer/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe("Dimensions and Metrics Explorer", () => {
// Wait for api promise to resolve so it won't render "fetching".
await renderer.act(async () => {
// metadata: { columns: { list: () => metadataColumnsPromise } },
await gapi.client.analytics.metadata.columns.list()
await gapi!.client!.analytics!.metadata!.columns!.list!()
// await gapi.client.analytics.management.accountSummaries.list()
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const useAnchorRedirects = (
const { hash, pathname } = useLocation()

useEffect(() => {
if (hash === "" || columns === undefined) {
if (hash === undefined || hash === "" || columns === undefined) {
return
}
if (hash.startsWith("#ga:")) {
Expand Down
11 changes: 7 additions & 4 deletions src/components/ViewSelector/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import Sut, { Label, TestID } from "./index"
import useAccountPropertyView from "./useAccountPropertyView"
import { StorageKey } from "@/constants"
import { fireEvent, within } from "@testing-library/react"
import { AccountSummary } from "@/types/ua"

enum QueryParam {
Account = "a",
Expand Down Expand Up @@ -49,12 +48,16 @@ describe("ViewSelector", () => {
})
test("can select account with no properties", async () => {
const accountName = "my account name"
const listAccountSummaries = jest.fn<Promise<AccountSummary[]>, any>()
const listAccountSummaries = jest.fn()
listAccountSummaries.mockReturnValue(
Promise.resolve([{ name: accountName, id: "account id", properties: [] }])
Promise.resolve({
result: {
items: [{ name: accountName, id: "account id", properties: [] }],
},
})
)
const { wrapped } = withProviders(<DefaultSut />, {
uaListAccountSummaries: listAccountSummaries,
ua: { listAccountSummaries },
})
const { findByTestId } = renderer.render(wrapped)

Expand Down
101 changes: 14 additions & 87 deletions src/components/ga4/StreamPicker/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ import * as React from "react"

import * as renderer from "@testing-library/react"
import "@testing-library/jest-dom"
import { renderHook } from "@testing-library/react-hooks"
import { act, within } from "@testing-library/react"

import { withProviders } from "@/test-utils"
import Sut, { Label } from "./index"
import useAccountPropertyStream from "./useAccountPropertyStream"
import { StorageKey } from "@/constants"
import useAccountProperty from "./useAccountProperty"

enum QueryParam {
Account = "a",
Expand All @@ -31,89 +29,18 @@ enum QueryParam {
}

describe("StreamPicker", () => {
test("Selects a property & stream when an account is picked.", async () => {
const { result } = renderHook(() =>
useAccountPropertyStream("a" as StorageKey, QueryParam)
)
const { gapi, wrapped } = withProviders(<Sut {...result.current} />)

const { findByTestId } = renderer.render(wrapped)

// Await for the mocked accountSummaries method to finish.
await act(async () => {
await act(async () => {
await gapi.client.analyticsadmin.accountSummaries.list({})
await gapi.client.analyticsadmin.accountSummaries.list({
pageToken: "1",
})
})
})

const accountPicker = await findByTestId(Label.Account)

await act(async () => {
const accountInput = within(accountPicker).getByRole("textbox")
accountPicker.focus()
renderer.fireEvent.change(accountInput, { target: { value: "" } })
renderer.fireEvent.keyDown(accountPicker, { key: "ArrowDown" })
renderer.fireEvent.keyDown(accountPicker, { key: "ArrowDown" })
renderer.fireEvent.keyDown(accountPicker, { key: "Enter" })
})

expect(within(accountPicker).getByRole("textbox")).toHaveValue("hi")
const DefaultPicker: React.FC = () => {
const ap = useAccountProperty("a" as StorageKey, QueryParam)
return <Sut {...ap} />
}
test("renders without error", async () => {
const { wrapped } = withProviders(<DefaultPicker />)
const { findByLabelText } = renderer.render(wrapped)

const account = await findByLabelText(Label.Account)
expect(account).toBeVisible()

const property = await findByLabelText(Label.Property)
expect(property).toBeVisible()
})
// describe("with defaults", () => {
// test("of { account } selects default", async () => {
// const account: AccountSummary = {
// name: "accountSummaries/def",
// account: "accounts/def456",
// displayName: "my second account",
// }
// const { gapi, wrapped } = withProviders(<Sut account={account} />)
// const { findByTestId } = renderer.render(wrapped)

// await act(async () => {
// await gapi.client.analyticsadmin.accountSummaries.list({})
// await gapi.client.analyticsadmin.accountSummaries.list({
// pageToken: "1",
// })
// })

// const accountPicker = await findByTestId(Label.Account)
// const accountInput = within(accountPicker).getByRole("textbox")

// expect(accountInput).toHaveValue("my second account")
// })

// test("of { account, property } selects default", async () => {
// const account: AccountSummary = {
// name: "accountSummaries/def",
// account: "accounts/def456",
// displayName: "my second account",
// }
// const property: PropertySummary = {
// displayName: "my fourth property",
// property: "properties/4",
// }
// const { gapi, wrapped } = withProviders(
// <Sut account={account} property={property} />
// )
// const { findByTestId } = renderer.render(wrapped)

// await act(async () => {
// await gapi.client.analyticsadmin.accountSummaries.list({})
// await gapi.client.analyticsadmin.accountSummaries.list({
// pageToken: "1",
// })
// // await gapi.client.analyticsadmin.properties.webDataStreams.list({})
// // await gapi.client.analyticsadmin.properties.iosAppDataStreams.list()
// // await gapi.client.analyticsadmin.properties.androidAppDataStreams.list()
// })

// const accountPicker = await findByTestId(Label.Account)
// const accountInput = within(accountPicker).getByRole("textbox")

// expect(accountInput).toHaveValue("my second account")
// })
// })
})
31 changes: 31 additions & 0 deletions src/components/ga4/StreamPicker/useAccounts.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import "@testing-library/jest-dom"
import { renderHook } from "@testing-library/react-hooks"

import useAccounts from "./useAccounts"
import { act } from "react-test-renderer"
import { RequestStatus } from "@/types"
import { wrapperFor } from "@/test-utils"

describe("useAccounts", () => {
beforeEach(() => {
window.localStorage.clear()
})

describe("when value not cached", () => {
test("sucessfully makes requests", async () => {
const { result, waitForNextUpdate } = renderHook(
() => {
return useAccounts()
},
{ wrapper: wrapperFor() }
)
expect(result.current.status).toEqual(RequestStatus.InProgress)

await act(async () => {
await waitForNextUpdate()
})

expect(result.current.status).toEqual(RequestStatus.Successful)
})
})
})
4 changes: 2 additions & 2 deletions src/components/ga4/StreamPicker/useAccounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ const useAccountSummaries = (): Requestable<AccountSummaries> => {
const requestReady = useMemo(() => adminAPI !== undefined, [adminAPI])

const paginatedRequest = useCallback(
(pageToken: string | undefined) => {
async (pageToken: string | undefined) => {
if (adminAPI === undefined) {
throw new Error(
"invalid invariant. adminAPI cannot be undefined when this method is called."
)
}
return adminAPI.accountSummaries.list({ pageToken })
return await adminAPI.accountSummaries.list({ pageToken })
},
[adminAPI]
)
Expand Down
49 changes: 24 additions & 25 deletions src/hooks/usePaginatedCallback.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,47 @@
import { useCallback } from "react"

const MaxPages = 100

const usePaginatedCallback = <T, U>(
requestReady: boolean,
errorMessage: string,
paginatedRequest: (pageToken: string | undefined) => gapi.client.Request<U>,
paginatedRequest: (
pageToken: string | undefined
) => Promise<gapi.client.Response<U>>,
getTs: (u: U) => T[] | undefined,
getPageToken: (u: U) => string | undefined,
onBeforeRequest?: () => void,
onError?: () => void
onBeforeRequest?: () => void
): (() => Promise<T[] | undefined>) => {
return useCallback(async () => {
try {
if (!requestReady) {
throw new Error(errorMessage)
}
onBeforeRequest && onBeforeRequest()
let pageToken: string | undefined = undefined
let ts: T[] = []
do {
pageToken = undefined
const u = await paginatedRequest(pageToken)

const nextTs = getTs(u.result)
if (!requestReady) {
throw new Error(errorMessage)
}
onBeforeRequest && onBeforeRequest()
let pageToken: string | undefined = undefined
let ts: T[] = []
let page = 0
do {
const u = await paginatedRequest(pageToken)

ts = ts.concat(nextTs || [])
const nextTs = getTs(u.result)

const nextPageToken = getPageToken(u.result)
ts = ts.concat(nextTs || [])

if (nextPageToken) {
pageToken = nextPageToken
}
} while (pageToken !== undefined)
return ts
} catch (e) {
onError && onError()
const nextPageToken = getPageToken(u.result)
pageToken = nextPageToken
page++
} while (pageToken !== undefined && page < MaxPages)
if (page >= MaxPages) {
throw new Error("went past max pagination.")
}
return ts
}, [
requestReady,
errorMessage,
paginatedRequest,
getTs,
getPageToken,
onBeforeRequest,
onError,
])
}

Expand Down
Loading

0 comments on commit a1acac2

Please sign in to comment.