-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c5e38d3
commit 384cccf
Showing
37 changed files
with
23,203 additions
and
15,650 deletions.
There are no files selected for viewing
74 changes: 74 additions & 0 deletions
74
...ents/data-board-external-tool-element/SharedExternalToolElementDisplayState.composable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import { useErrorHandler } from "@/components/error-handling/ErrorHandler.composable"; | ||
import { ToolContextType } from "@/serverApi/v3"; | ||
import { ExternalToolDisplayData } from "@/store/external-tool"; | ||
import { createTestableSharedComposable } from "@/utils/create-shared-composable"; | ||
import { useContextExternalToolApi } from "@data-external-tool"; | ||
import { ref, Ref } from "vue"; | ||
|
||
export const useSharedExternalToolElementDisplayState = | ||
createTestableSharedComposable(() => { | ||
const { handleError } = useErrorHandler(); | ||
const { fetchDisplayDataCall } = useContextExternalToolApi(); | ||
const displayDataMap: Map<string, Ref<ExternalToolDisplayData[]>> = new Map< | ||
string, | ||
Ref<ExternalToolDisplayData[]> | ||
>(); | ||
const isLoading: Ref<boolean> = ref(false); | ||
|
||
const getDisplayDataList = ( | ||
cardId: string | ||
): Ref<ExternalToolDisplayData[]> | undefined => { | ||
const displayDataList: Ref<ExternalToolDisplayData[]> | undefined = | ||
displayDataMap.get(cardId); | ||
|
||
return displayDataList; | ||
}; | ||
|
||
const fetchDisplayData = async (cardId: string): Promise<void> => { | ||
isLoading.value = true; | ||
|
||
try { | ||
let displayDataList: Ref<ExternalToolDisplayData[]> | undefined = | ||
getDisplayDataList(cardId); | ||
|
||
if (!displayDataList?.value) { | ||
displayDataList = ref([]); | ||
|
||
displayDataMap.set(cardId, displayDataList); | ||
} | ||
|
||
displayDataList.value = await fetchDisplayDataCall( | ||
cardId, | ||
ToolContextType.BoardCard | ||
); | ||
} catch (error) { | ||
handleError(error); | ||
} | ||
|
||
isLoading.value = false; | ||
}; | ||
|
||
const findDisplayData = ( | ||
cardId: string, | ||
contextExternalToolId: string | ||
): ExternalToolDisplayData | undefined => { | ||
const displayDataList: Ref<ExternalToolDisplayData[]> | undefined = | ||
getDisplayDataList(cardId); | ||
|
||
const displayData: ExternalToolDisplayData | undefined = | ||
displayDataList?.value.find( | ||
(externalToolDisplayData: ExternalToolDisplayData) => | ||
externalToolDisplayData.contextExternalToolId === | ||
contextExternalToolId | ||
); | ||
|
||
return displayData; | ||
}; | ||
|
||
return { | ||
isLoading, | ||
getDisplayDataList, | ||
fetchDisplayData, | ||
findDisplayData, | ||
}; | ||
}); |
142 changes: 142 additions & 0 deletions
142
...data-board-external-tool-element/SharedExternalToolElementDisplayState.composable.unit.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import { useErrorHandler } from "@/components/error-handling/ErrorHandler.composable"; | ||
import { ToolContextType } from "@/serverApi/v3"; | ||
import { ExternalToolDisplayData } from "@/store/external-tool"; | ||
import { externalToolDisplayDataFactory } from "@@/tests/test-utils"; | ||
import { useContextExternalToolApi } from "@data-external-tool"; | ||
import { createMock, DeepMocked } from "@golevelup/ts-jest"; | ||
import { Ref } from "vue"; | ||
import { useSharedExternalToolElementDisplayState } from "./SharedExternalToolElementDisplayState.composable"; | ||
|
||
jest.mock("@data-external-tool"); | ||
jest.mock("@/components/error-handling/ErrorHandler.composable"); | ||
jest.mock<typeof import("@/utils/create-shared-composable")>( | ||
"@/utils/create-shared-composable", | ||
() => ({ | ||
createTestableSharedComposable: (composable) => composable, | ||
}) | ||
); | ||
|
||
describe("SharedExternalToolElementDisplayState.composable", () => { | ||
let useContextExternalToolApiMock: DeepMocked< | ||
ReturnType<typeof useContextExternalToolApi> | ||
>; | ||
let useErrorHandlerMock: DeepMocked<ReturnType<typeof useErrorHandler>>; | ||
|
||
beforeEach(() => { | ||
useContextExternalToolApiMock = | ||
createMock<ReturnType<typeof useContextExternalToolApi>>(); | ||
useErrorHandlerMock = createMock<ReturnType<typeof useErrorHandler>>(); | ||
|
||
jest | ||
.mocked(useContextExternalToolApi) | ||
.mockReturnValue(useContextExternalToolApiMock); | ||
jest.mocked(useErrorHandler).mockReturnValue(useErrorHandlerMock); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
describe("when no data is loaded", () => { | ||
it("should have no data lists", async () => { | ||
const displayDataState = useSharedExternalToolElementDisplayState(); | ||
|
||
const result: Ref<ExternalToolDisplayData[]> | undefined = | ||
displayDataState.getDisplayDataList("cardId"); | ||
|
||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
it("should not find data", async () => { | ||
const displayDataState = useSharedExternalToolElementDisplayState(); | ||
|
||
const result: ExternalToolDisplayData | undefined = | ||
displayDataState.findDisplayData("cardId", "contextExternalToolId"); | ||
|
||
expect(result).toBeUndefined(); | ||
}); | ||
}); | ||
|
||
describe("when data is loaded", () => { | ||
const setup = () => { | ||
const displayData: ExternalToolDisplayData = | ||
externalToolDisplayDataFactory.build(); | ||
|
||
useContextExternalToolApiMock.fetchDisplayDataCall.mockResolvedValue([ | ||
displayData, | ||
]); | ||
|
||
return { | ||
displayData, | ||
...useSharedExternalToolElementDisplayState(), | ||
}; | ||
}; | ||
|
||
it("should call the api for display data of the card", async () => { | ||
const { fetchDisplayData } = setup(); | ||
|
||
await fetchDisplayData("cardId"); | ||
|
||
expect( | ||
useContextExternalToolApiMock.fetchDisplayDataCall | ||
).toHaveBeenCalledWith("cardId", ToolContextType.BoardCard); | ||
}); | ||
|
||
it("should set the display data in the state", async () => { | ||
const { fetchDisplayData, getDisplayDataList, displayData } = setup(); | ||
|
||
await fetchDisplayData("cardId"); | ||
const result: Ref<ExternalToolDisplayData[]> | undefined = | ||
getDisplayDataList("cardId"); | ||
|
||
expect(result?.value).toEqual([displayData]); | ||
}); | ||
|
||
it("should find the display data for a specific tool", async () => { | ||
const { fetchDisplayData, findDisplayData, displayData } = setup(); | ||
|
||
await fetchDisplayData("cardId"); | ||
const result: ExternalToolDisplayData | undefined = findDisplayData( | ||
"cardId", | ||
displayData.contextExternalToolId | ||
); | ||
|
||
expect(result).toEqual(displayData); | ||
}); | ||
|
||
it("should not find data for non-existing tools", async () => { | ||
const { fetchDisplayData, findDisplayData } = setup(); | ||
|
||
await fetchDisplayData("cardId"); | ||
const result: ExternalToolDisplayData | undefined = findDisplayData( | ||
"cardId", | ||
"otherId" | ||
); | ||
|
||
expect(result).toBeUndefined(); | ||
}); | ||
}); | ||
|
||
describe("when an error occurs during loading", () => { | ||
const setup = () => { | ||
const error = new Error("unable to load"); | ||
|
||
useContextExternalToolApiMock.fetchDisplayDataCall.mockRejectedValue( | ||
error | ||
); | ||
|
||
return { | ||
error, | ||
...useSharedExternalToolElementDisplayState(), | ||
}; | ||
}; | ||
|
||
it("should handle the error", async () => { | ||
const { fetchDisplayData, error } = setup(); | ||
|
||
await fetchDisplayData("cardId"); | ||
|
||
expect(useErrorHandlerMock.handleError).toHaveBeenCalledWith(error); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./SharedExternalToolElementDisplayState.composable"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
src/components/data-external-tool/ContextExternalToolApi.composable.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { | ||
ToolApiFactory, | ||
ToolApiInterface, | ||
ToolContextType, | ||
ToolReferenceListResponse, | ||
} from "@/serverApi/v3"; | ||
import { ExternalToolDisplayData } from "@/store/external-tool"; | ||
import { ExternalToolMapper } from "@/store/external-tool/mapper"; | ||
import { $axios } from "@/utils/api"; | ||
import { AxiosResponse } from "axios"; | ||
|
||
export const useContextExternalToolApi = () => { | ||
const toolApi: ToolApiInterface = ToolApiFactory(undefined, "/v3", $axios); | ||
|
||
const fetchDisplayDataCall = async ( | ||
contextId: string, | ||
contextType: ToolContextType | ||
): Promise<ExternalToolDisplayData[]> => { | ||
const response: AxiosResponse<ToolReferenceListResponse> = | ||
await toolApi.toolControllerGetToolReferences(contextId, contextType); | ||
|
||
const mapped: ExternalToolDisplayData[] = | ||
ExternalToolMapper.mapToExternalToolDisplayData(response.data); | ||
|
||
return mapped; | ||
}; | ||
|
||
return { | ||
fetchDisplayDataCall, | ||
}; | ||
}; |
75 changes: 75 additions & 0 deletions
75
src/components/data-external-tool/ContextExternalToolApi.composable.unit.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import * as serverApi from "@/serverApi/v3/api"; | ||
import { ToolContextType, ToolReferenceResponse } from "@/serverApi/v3/api"; | ||
import { | ||
ExternalToolDisplayData, | ||
ToolConfigurationStatus, | ||
} from "@/store/external-tool"; | ||
import { | ||
mockApiResponse, | ||
toolReferenceResponseFactory, | ||
} from "@@/tests/test-utils"; | ||
import { createMock, DeepMocked } from "@golevelup/ts-jest"; | ||
import { useContextExternalToolApi } from "./ContextExternalToolApi.composable"; | ||
|
||
describe("ContextExternalToolApi.composable", () => { | ||
let toolApi: DeepMocked<serverApi.ToolApiInterface>; | ||
|
||
beforeEach(() => { | ||
toolApi = createMock<serverApi.ToolApiInterface>(); | ||
|
||
jest.spyOn(serverApi, "ToolApiFactory").mockReturnValue(toolApi); | ||
}); | ||
|
||
afterEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
describe("fetchDisplayDataCall", () => { | ||
const setup = () => { | ||
const displayData: ToolReferenceResponse = | ||
toolReferenceResponseFactory.build({ logoUrl: "mockLogoUrl" }); | ||
|
||
toolApi.toolControllerGetToolReferences.mockResolvedValue( | ||
mockApiResponse({ data: { data: [displayData] } }) | ||
); | ||
|
||
return { | ||
displayData, | ||
}; | ||
}; | ||
|
||
it("should call the api for tool references", async () => { | ||
setup(); | ||
|
||
await useContextExternalToolApi().fetchDisplayDataCall( | ||
"cardId", | ||
ToolContextType.BoardCard | ||
); | ||
|
||
expect(toolApi.toolControllerGetToolReferences).toHaveBeenCalledWith( | ||
"cardId", | ||
ToolContextType.BoardCard | ||
); | ||
}); | ||
|
||
it("should return an array of display data", async () => { | ||
const { displayData } = setup(); | ||
|
||
const result: ExternalToolDisplayData[] = | ||
await useContextExternalToolApi().fetchDisplayDataCall( | ||
"courseId", | ||
ToolContextType.Course | ||
); | ||
|
||
expect(result).toEqual<ExternalToolDisplayData[]>([ | ||
{ | ||
contextExternalToolId: displayData.contextToolId, | ||
name: displayData.displayName, | ||
logoUrl: displayData.logoUrl, | ||
status: ToolConfigurationStatus.Latest, | ||
openInNewTab: displayData.openInNewTab, | ||
}, | ||
]); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./ContextExternalToolApi.composable"; |
Oops, something went wrong.