132 lines
3.7 KiB
Vue
132 lines
3.7 KiB
Vue
<template>
|
|
<div class="bg-m-secondary w-[509px] h-[184px] mx-4 rounded-md shadow-md/50 shadow-black p-2">
|
|
<div class="mb-2 flex items-center justify-between">
|
|
<p class="font-bold text-3xl text-m-tertiary">
|
|
Speedtest
|
|
</p>
|
|
<IconifyIcon
|
|
icon="mdi:reload"
|
|
class="bg-m-tertiary text-2xl text-black rounded-md shadow-md/50 mr-1 cursor-pointer"
|
|
@Click="runTests"
|
|
/>
|
|
</div>
|
|
<div class="grid grid-cols-3 gap-3">
|
|
<div class="bg-m-tertiary w-[153px] h-[120px] rounded-md shadow-md/50 shadow-m-black">
|
|
<div class="flex items-center justify-center">
|
|
<IconifyIcon
|
|
icon="mdi:download"
|
|
class="text-m-primary text-2xl mt-2 ml-1"
|
|
/>
|
|
<p class="font-bold uppercase text-xl text-m-text mt-2 mr-1">
|
|
download
|
|
</p>
|
|
</div>
|
|
<div class="mx-2 flex flex-col items-center justify-center">
|
|
<span class="text-4xl">
|
|
{{ download !== null ? `${download}` : "..." }}
|
|
</span>
|
|
<p class="font-bold text-xl leading-tight">
|
|
Mbps
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="bg-m-tertiary w-[153px] h-[120px] rounded-md shadow-md/50 shadow-m-black">
|
|
<div class="flex items-center justify-center">
|
|
<IconifyIcon
|
|
icon="mdi:upload"
|
|
class="text-m-primary text-2xl mt-2 ml-1"
|
|
/>
|
|
<p class="font-bold uppercase text-xl text-m-text mt-2 mr-1">
|
|
upload
|
|
</p>
|
|
</div>
|
|
<div class="mx-2 flex flex-col items-center justify-center">
|
|
<span class="text-4xl">
|
|
{{ upload !== null ? `${upload}` : "..." }}
|
|
</span>
|
|
<p class="font-bold text-xl leading-tight">
|
|
Mbps
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="bg-m-tertiary w-[153px] h-[120px] rounded-md shadow-md/50 shadow-m-black">
|
|
<div class="flex items-center justify-center">
|
|
<IconifyIcon
|
|
icon="mdi:wifi"
|
|
class="text-m-primary text-2xl mt-2 ml-1"
|
|
/>
|
|
<p class="font-bold uppercase text-xl text-m-text mt-2 mr-1">
|
|
ping
|
|
</p>
|
|
</div>
|
|
<div class="mx-2 flex flex-col items-center justify-center">
|
|
<span class="text-4xl">
|
|
{{ ping !== null ? `${ping}` : "..." }}
|
|
</span>
|
|
<p class="font-bold text-xl leading-tight">
|
|
Ms
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script setup lang="ts">
|
|
import {onMounted, ref} from "vue";
|
|
import {Icon as IconifyIcon} from "@iconify/vue"
|
|
|
|
const ping = ref<number | null>(null)
|
|
const download = ref<number | null>(null)
|
|
const upload = ref<number | null>(null)
|
|
|
|
async function testDownload() {
|
|
const start = performance.now()
|
|
|
|
const res = await fetch('/api/download')
|
|
const blob = await res.blob()
|
|
|
|
const end = performance.now()
|
|
|
|
const size = blob.size
|
|
const seconds = (end - start) / 1000
|
|
download.value = Math.round((size * 8) / seconds / 1000000)
|
|
}
|
|
|
|
async function testUpload() {
|
|
const size = 5 * 1024 * 1024
|
|
const data = new Uint8Array(size)
|
|
|
|
const start = performance.now()
|
|
|
|
await fetch('/api/upload', {
|
|
method: 'POST',
|
|
body: data
|
|
})
|
|
|
|
const end = performance.now()
|
|
|
|
const seconds = (end - start) / 1000
|
|
upload.value = Math.round((size * 8) / seconds / 1000000)
|
|
}
|
|
|
|
|
|
async function testPing() {
|
|
const start = performance.now()
|
|
|
|
await fetch('/api/ping')
|
|
|
|
const end = performance.now()
|
|
|
|
ping.value = Math.round(end - start)
|
|
}
|
|
|
|
async function runTests() {
|
|
await testDownload()
|
|
await testUpload()
|
|
await testPing()
|
|
}
|
|
onMounted(() => {
|
|
runTests()
|
|
})
|
|
</script>
|