feat(frontend): files API stub instead of hardcoded mocks (#3)

* build(frontend): node version management

* feat: use files API via network instead of hardcoded mock

* fix: mock in tests
This commit is contained in:
Marc 2023-08-09 00:52:26 -04:00 committed by GitHub
parent c541877cf7
commit 002b6cdc68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 168 additions and 38 deletions

View file

@ -49,4 +49,9 @@ tasks:
cmds:
- yarn start
dir: frontend
fe.test:
desc: "Runs the frontend test suite."
deps: [fe.bootstrap]
cmds:
- yarn test
dir: frontend

1
frontend/.n Normal file
View file

@ -0,0 +1 @@
hydrogen

View file

@ -1 +0,0 @@
lts/hydrogen

View file

@ -6,7 +6,8 @@
"@mui/icons-material": "^5.14.1",
"@mui/material": "^5.14.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-query": "^3.39.3"
},
"scripts": {
"start": "parcel serve src/index.html --no-cache",

View file

@ -1,7 +1,7 @@
#!/bin/bash
if [[ $CI != 1 ]]; then
nvm use
n $(cat .n)
fi
corepack enable && yarn

View file

@ -1,25 +1,13 @@
import { Box } from "@mui/material"
import { QueryClient, QueryClientProvider, useQuery } from "react-query"
import NavigationBar from "./components/NavigationBar"
import FileList from "./components/FileList"
import FileDetails from "./components/FileDetails"
import AsyncTaskContext from "./contexts/AsyncTaskContext"
import LocationContext, { useLocationContext } from "./contexts/LocationContext"
import { useOwnFileList } from "./queries/files"
const mockData = [
{
title: "Test file",
filename: "testfile.txt",
size: 1023,
uid: "123",
},
{
title: "Other file",
filename: "testfile2.txt",
size: 535346,
uid: "456",
},
]
const routeLabels = {
ITEM_DETAILS: "item-details",
}
@ -30,13 +18,16 @@ const routes = {
const App = () => {
const { location } = useLocationContext()
const { isLoading, data } = useOwnFileList()
if (isLoading) return
return (
<Box sx={{ display: "flex", flexDirection: "column", width: "100%" }}>
<NavigationBar />
<Box component="main" sx={{ display: "flex", paddingTop: "10px" }}>
<Box component="div" sx={{ flexGrow: 1 }}>
<FileList data={mockData} />
<FileList data={data} />
</Box>
{location.label === routeLabels.ITEM_DETAILS ? (
<Box component="div" sx={{ flexGrow: 1 }}>
@ -48,12 +39,16 @@ const App = () => {
)
}
const queryClient = new QueryClient()
const AppWithContexts = () => (
<AsyncTaskContext>
<LocationContext routes={routes}>
<App />
</LocationContext>
</AsyncTaskContext>
<QueryClientProvider client={queryClient}>
<AsyncTaskContext>
<LocationContext routes={routes}>
<App />
</LocationContext>
</AsyncTaskContext>
</QueryClientProvider>
)
export default AppWithContexts

View file

@ -7,17 +7,17 @@ import MuiDeleteIcon from "@mui/icons-material/Delete"
import MuiDownloadIcon from "@mui/icons-material/Download"
import MuiIconButton from "@mui/material/IconButton"
import { useFileDetails } from "../queries/files"
interface FileDetailsProps {
itemId: string
}
// TODO: API data.
const mockData = {
title: "My File",
size: 123123123,
}
function FileDetails({ itemId }: FileDetailsProps) {
const { isLoading, data } = useFileDetails(itemId)
if (isLoading) return null
const handleDownloadClick = () => {
console.log("download click")
}
@ -26,6 +26,8 @@ function FileDetails({ itemId }: FileDetailsProps) {
console.log("delete click")
}
const currentFileDetails = data
return (
<MuiCard sx={{ height: "100%", display: "flex", flexDirection: "column" }}>
<MuiBox
@ -34,9 +36,11 @@ function FileDetails({ itemId }: FileDetailsProps) {
>
<MuiArticleIcon sx={{ fontSize: 120 }} />
<MuiTypography variant="h1" sx={{ fontSize: 30 }}>
{mockData.title}
{currentFileDetails.title ?? currentFileDetails.filename}
</MuiTypography>
<MuiTypography>
{byteSizeToUnits(currentFileDetails.size)}
</MuiTypography>
<MuiTypography>{byteSizeToUnits(mockData.size)}</MuiTypography>
</MuiBox>
<MuiBox sx={{ display: "flex", justifyContent: "center" }}>
<>

View file

@ -23,7 +23,7 @@ interface FileListItemData {
/* Size of the file in bytes. */
size: number
/* Unique identifier */
uid: string
id: string
}
interface FileListProps {
@ -110,7 +110,7 @@ function FileList({ data }: FileListProps) {
size={itemData.size}
filename={itemData.filename}
onClickHandler={() =>
onClickHandler("uid" in itemData ? itemData.uid : "")
onClickHandler("id" in itemData ? itemData.id : "")
}
onDownloadHandler={onDownloadHandler}
onDeleteHandler={onDeleteHandler}

View file

@ -0,0 +1,19 @@
import { useQuery } from "react-query"
function useOwnFileList() {
return useQuery("file-list", async () => {
const response = await fetch("http://localhost:8000/files/")
return response.json()
})
}
function useFileDetails(fileId: string) {
return useQuery(`file-details-${fileId}`, async () => {
const response = await fetch(`http://localhost:8000/files/${fileId}/`)
return response.json()
})
}
export { useOwnFileList, useFileDetails }

View file

@ -5,8 +5,8 @@ import FileList from "../src/components/FileList"
describe("FileList", () => {
const mockItems = [
{ title: "Item 1", filename: "item1.txt", size: 1, uid: "123" },
{ title: "Item 2", filename: "item2.txt", size: 1, uid: "456" },
{ title: "Item 1", filename: "item1.txt", size: 1, id: "123" },
{ title: "Item 2", filename: "item2.txt", size: 1, id: "456" },
]
const mockAsyncTasks = [

View file

@ -362,7 +362,7 @@ __metadata:
languageName: node
linkType: hard
"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7":
"@babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.22.6, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.2, @babel/runtime@npm:^7.7.2, @babel/runtime@npm:^7.8.7":
version: 7.22.6
resolution: "@babel/runtime@npm:7.22.6"
dependencies:
@ -2734,6 +2734,13 @@ __metadata:
languageName: node
linkType: hard
"big-integer@npm:^1.6.16":
version: 1.6.51
resolution: "big-integer@npm:1.6.51"
checksum: 3d444173d1b2e20747e2c175568bedeebd8315b0637ea95d75fd27830d3b8e8ba36c6af40374f36bdaea7b5de376dcada1b07587cb2a79a928fccdb6e6e3c518
languageName: node
linkType: hard
"boolbase@npm:^1.0.0":
version: 1.0.0
resolution: "boolbase@npm:1.0.0"
@ -2769,6 +2776,22 @@ __metadata:
languageName: node
linkType: hard
"broadcast-channel@npm:^3.4.1":
version: 3.7.0
resolution: "broadcast-channel@npm:3.7.0"
dependencies:
"@babel/runtime": ^7.7.2
detect-node: ^2.1.0
js-sha3: 0.8.0
microseconds: 0.2.0
nano-time: 1.0.0
oblivious-set: 1.0.0
rimraf: 3.0.2
unload: 2.2.0
checksum: 803794c48dcce7f03aca69797430bd8b1c4cfd70b7de22079cd89567eeffaa126a1db98c7c2d86af8131d9bb41ed367c0fef96dfb446151c927b831572c621fc
languageName: node
linkType: hard
"browserslist@npm:^4.21.9, browserslist@npm:^4.6.6":
version: 4.21.10
resolution: "browserslist@npm:4.21.10"
@ -3280,6 +3303,13 @@ __metadata:
languageName: node
linkType: hard
"detect-node@npm:^2.0.4, detect-node@npm:^2.1.0":
version: 2.1.0
resolution: "detect-node@npm:2.1.0"
checksum: 832184ec458353e41533ac9c622f16c19f7c02d8b10c303dfd3a756f56be93e903616c0bb2d4226183c9351c15fc0b3dba41a17a2308262afabcfa3776e6ae6e
languageName: node
linkType: hard
"diff-sequences@npm:^29.4.3":
version: 29.4.3
resolution: "diff-sequences@npm:29.4.3"
@ -4868,6 +4898,13 @@ __metadata:
languageName: node
linkType: hard
"js-sha3@npm:0.8.0":
version: 0.8.0
resolution: "js-sha3@npm:0.8.0"
checksum: 75df77c1fc266973f06cce8309ce010e9e9f07ec35ab12022ed29b7f0d9c8757f5a73e1b35aa24840dced0dea7059085aa143d817aea9e188e2a80d569d9adce
languageName: node
linkType: hard
"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0":
version: 4.0.0
resolution: "js-tokens@npm:4.0.0"
@ -5224,6 +5261,16 @@ __metadata:
languageName: node
linkType: hard
"match-sorter@npm:^6.0.2":
version: 6.3.1
resolution: "match-sorter@npm:6.3.1"
dependencies:
"@babel/runtime": ^7.12.5
remove-accents: 0.4.2
checksum: a4b02b676ac4ce64a89a091539ee4a70a802684713bcf06f2b70787927f510fe8a2adc849f9288857a90906083ad303467e530e8723b4a9756df9994fc164550
languageName: node
linkType: hard
"mdn-data@npm:2.0.14":
version: 2.0.14
resolution: "mdn-data@npm:2.0.14"
@ -5248,6 +5295,13 @@ __metadata:
languageName: node
linkType: hard
"microseconds@npm:0.2.0":
version: 0.2.0
resolution: "microseconds@npm:0.2.0"
checksum: 22bfa8553f92c7d95afff6de0aeb2aecf750680d41b8c72b02098ccc5bbbb0a384380ff539292dbd3788f5dfc298682f9d38a2b4c101f5ee2c9471d53934c5fa
languageName: node
linkType: hard
"mime-db@npm:1.52.0":
version: 1.52.0
resolution: "mime-db@npm:1.52.0"
@ -5451,6 +5505,15 @@ __metadata:
languageName: node
linkType: hard
"nano-time@npm:1.0.0":
version: 1.0.0
resolution: "nano-time@npm:1.0.0"
dependencies:
big-integer: ^1.6.16
checksum: eef8548546cc1020625f8e44751a7263e9eddf0412a6a1a6c80a8d2be2ea7973622804a977cdfe796807b85b20ff6c8ba340e8dd20effcc7078193ed5edbb5d4
languageName: node
linkType: hard
"natural-compare@npm:^1.4.0":
version: 1.4.0
resolution: "natural-compare@npm:1.4.0"
@ -5645,6 +5708,13 @@ __metadata:
languageName: node
linkType: hard
"oblivious-set@npm:1.0.0":
version: 1.0.0
resolution: "oblivious-set@npm:1.0.0"
checksum: f31740ea9c3a8242ad2324e4ebb9a35359fbc2e6e7131731a0fc1c8b7b1238eb07e4c8c631a38535243a7b8e3042b7e89f7dc2a95d2989afd6f80bd5793b0aab
languageName: node
linkType: hard
"once@npm:^1.3.0":
version: 1.4.0
resolution: "once@npm:1.4.0"
@ -6014,6 +6084,24 @@ __metadata:
languageName: node
linkType: hard
"react-query@npm:^3.39.3":
version: 3.39.3
resolution: "react-query@npm:3.39.3"
dependencies:
"@babel/runtime": ^7.5.5
broadcast-channel: ^3.4.1
match-sorter: ^6.0.2
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
peerDependenciesMeta:
react-dom:
optional: true
react-native:
optional: true
checksum: d2de6a0992dbf039ff2de564de1ae6361f8ac7310159dae42ec16f833b79c05caedced187235c42373ac331cc5f2fe9e2b31b14ae75a815e86d86e30ca9887ad
languageName: node
linkType: hard
"react-refresh@npm:^0.9.0":
version: 0.9.0
resolution: "react-refresh@npm:0.9.0"
@ -6074,6 +6162,13 @@ __metadata:
languageName: node
linkType: hard
"remove-accents@npm:0.4.2":
version: 0.4.2
resolution: "remove-accents@npm:0.4.2"
checksum: 84a6988555dea24115e2d1954db99509588d43fe55a1590f0b5894802776f7b488b3151c37ceb9e4f4b646f26b80b7325dcea2fae58bc3865df146e1fa606711
languageName: node
linkType: hard
"require-directory@npm:^2.1.1":
version: 2.1.1
resolution: "require-directory@npm:2.1.1"
@ -6151,7 +6246,7 @@ __metadata:
languageName: node
linkType: hard
"rimraf@npm:^3.0.2":
"rimraf@npm:3.0.2, rimraf@npm:^3.0.2":
version: 3.0.2
resolution: "rimraf@npm:3.0.2"
dependencies:
@ -6212,6 +6307,7 @@ __metadata:
process: ^0.11.10
react: ^18.2.0
react-dom: ^18.2.0
react-query: ^3.39.3
rome: ^12.1.3
ts-jest: ^29.1.1
typescript: ^5.1.6
@ -6766,6 +6862,16 @@ __metadata:
languageName: node
linkType: hard
"unload@npm:2.2.0":
version: 2.2.0
resolution: "unload@npm:2.2.0"
dependencies:
"@babel/runtime": ^7.6.2
detect-node: ^2.0.4
checksum: 88ba950c5ff83ab4f9bbd8f63bbf19ba09687ed3c434efd43b7338cc595bc574df8f9b155ee6eee7a435de3d3a4a226726988428977a68ba4907045f1fac5d41
languageName: node
linkType: hard
"update-browserslist-db@npm:^1.0.11":
version: 1.0.11
resolution: "update-browserslist-db@npm:1.0.11"