Skip to content

Instantly share code, notes, and snippets.

@alfianyusufabdullah
Created July 8, 2021 06:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alfianyusufabdullah/fa492fd8789e7d0f9eec9abc4f8e711d to your computer and use it in GitHub Desktop.
Save alfianyusufabdullah/fa492fd8789e7d0f9eec9abc4f8e711d to your computer and use it in GitHub Desktop.
playground
let tabId
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (chrome.runtime.lastError){
console.log(chrome.runtime.lastError.message);
return
}
tabId = sender.tab.id
sendResponse("Message Received!")
});
chrome.downloads.onChanged.addListener(function (delta) {
if (!delta.state ||
(delta.state.current != 'complete')) {
return;
}
chrome.downloads.search({ id: delta.id }, (results) => {
let item = results[0]
chrome.tabs.sendMessage(tabId, item.filename, function(response) {
if (chrome.runtime.lastError){
console.log(chrome.runtime.lastError.message);
return
}
console.log("CS received my message!");
});
})
});
const courseName = "Submission Bookshelf API"
const url = window.location.href.split("/")
const submissionId = url[url.length - 2]
const message = (type, data, other) => JSON.stringify({ type: type, data: data, other: other })
const incommingMessage = event => JSON.parse(event.data)
let statusView
let statusOverview
let resultView
let textView
let serverFile
let buttonRunServer
window.onload = () => {
const currentOpenedCourse = document.querySelectorAll(".form-control-static")[6].innerText
if (currentOpenedCourse == courseName) {
injectResultCard()
}
}
function injectResultCard() {
const cardResult = document.createElement("div")
cardResult.innerHTML = content()
cardResult.className = "card card-default mb-4"
const cardCriteria = document.querySelectorAll(".card.card-default.mb-4")
const cardCriteriaInPosition = cardCriteria[cardCriteria.length - 2]
cardCriteriaInPosition.parentNode.insertBefore(cardResult, cardCriteriaInPosition)
statusView = document.getElementById("status")
statusOverview = document.getElementById("status-overview")
resultView = document.getElementById("result")
textView = document.getElementById("text-overview")
buttonRunServer = document.getElementById("run")
buttonRunServer.onclick = event => {
console.log("try to run server");
socket.send(message("run", serverFile, null))
}
}
function content() {
return `
<div class="card-header">
<strong>Submission Test Result</strong>
</div>
<div class="card-body">
<div>
<div class="alert alert-success d-flex justify-content-between align-items-center" id="status-overview">
<div style="text-align: left!important">
<span style="white-space: pre-line" id="text-overview">Silakan download submission untuk memulai pengujian</span>
</div>
<div style="text-align: right!important">
<button style="display: none" id="run" class="btn btn-danger">Run Server</a>
</div>
</div>
<p id="status"><strong>Status:</strong></p>
<p id="result"><strong>Result:</strong></p>
</div>
`
}
const socket = new WebSocket("ws://localhost:1111/backend");
socket.onopen = () => {
console.log("Connected to local server");
}
socket.onerror = () => {
console.log('error!');
}
socket.onmessage = event => {
const message = incommingMessage(event)
if (message.type == "run-status"){
textView.textContent = message.data
}
if (message.type == "pathserver") {
serverFile = message.data
console.log("Server file recorded: " + serverFile);
}
if (message.type === "update") {
if (message.data.includes("Server exit with")) {
statusView.innerHTML = `<strong>Status: </strong>Server going to offline`
return
}
statusView.innerHTML = `<strong>Status: </strong>${message.data}`
}
if (message.type == "result") {
const failures = JSON.parse(message.data).Run.Failures
if (failures.length > 0) {
const optionalTest = failures.filter(test => {
return test.Source.Name.includes("[Optional]")
})
const mandatory = failures.filter(test => {
return test.Source.Name.includes("[Mandatory]")
})
console.log("Mandatory test fail:" + mandatory.length);
if (mandatory.length > 0) {
textView.textContent = "Terdapat beberapa pengujian Mandatory yang gagal dijalankan.\nSilakan jalankan server dan periksa dengan Postman"
statusOverview.classList.remove("alert-success")
statusOverview.classList.add("alert-danger")
resultView.innerHTML = `<strong>Result: </strong>Failure`
buttonRunServer.style.display = "block"
return
}
if (optionalTest.length < 5) {
textView.textContent = "Seluruh pengujian Mandatory berhasil dijalankan. Silakan diterima dengan bintang 4"
resultView.innerHTML = `<strong>Result: </strong>Success`
return
}
} else {
textView.textContent = "Seluruh pengujian Mandatory dan Optional berhasil dijalankan. Silakan diterima dengan bintang 5"
resultView.innerHTML = `<strong>Result: </strong>Success`
}
}
};
chrome.runtime.sendMessage({ text: "hey" }, function (response) {
console.log(response);
});
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
textView.textContent = "Memulai pengujian"
socket.send(message("process", submissionId, msg))
});
fun main() {
embeddedServer(Netty, port = 1111, host = "localhost") {
install(WebSockets)
routing {
val connections: MutableSet<Connection?> = Collections.synchronizedSet<Connection?>(LinkedHashSet())
webSocket("/backend") {
val thisConnection = Connection(this)
connections += thisConnection
try {
for (frame in incoming) {
frame as? Frame.Text ?: continue
val receivedText = frame.readText()
connections.filterNotNull().forEach {
it.session.send(receivedText)
}
}
} catch (e: Exception) {
println(e.localizedMessage)
} finally {
connections -= thisConnection
}
}
}
}.start(wait = true)
}
class Connection(val session: DefaultWebSocketSession) {
companion object {
var lastId = AtomicInteger(0)
}
}
data class IncomingMessage(val type: String, val data: String, val other: String?)
private class StreamGobbler(private val inputStream: InputStream, private val consumer: Consumer<String>) : Runnable {
override fun run() {
BufferedReader(InputStreamReader(inputStream)).lines()
.forEach(consumer)
}
}
private const val newmanCollectionPath = "/home/dicoding/Documents/collection-postman"
fun main() {
val client = OkHttpClient()
val request = Request.Builder().url("ws://localhost:1111/backend").build()
val socketClient = object : WebSocketListener() {
override fun onOpen(webSocket: WebSocket, response: Response) {
super.onOpen(webSocket, response)
println("Connection open!")
}
override fun onMessage(webSocket: WebSocket, text: String) {
super.onMessage(webSocket, text)
val incomingMessage = Gson().fromJson(text, IncomingMessage::class.java)
when (incomingMessage.type) {
"process" -> {
run("killall node")
println("Processing submission id ${incomingMessage.data} with file ${incomingMessage.other?.split("/")?.last()}")
webSocket.send(Gson().toJson(IncomingMessage("update", "Submission di proses", null)))
try {
extractSubmissionsFolder(
webSocket,
incomingMessage.other ?: "",
"/home/dicoding/project/backend-submission/${incomingMessage.data}-${System.currentTimeMillis()}/"
)
} catch (e: Exception) {
println(e.message)
send(webSocket, "update", "Something Happen")
}
}
"run" -> {
run("killall node")
runningServer(webSocket, "node ${incomingMessage.data}") {
send(webSocket, "run-status", "Server Running")
}
}
}
}
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
super.onClosing(webSocket, code, reason)
println("On closing message: $reason")
}
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
super.onClosed(webSocket, code, reason)
println("On closed message: $reason")
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
super.onFailure(webSocket, t, response)
println("On failure message: ${t.message}")
}
}
client.newWebSocket(request, socketClient)
client.dispatcher().executorService().shutdown()
}
fun extractSubmissionsFolder(socket: WebSocket, file: String, targetPaths: String) {
val sourcePath = Paths.get(file)
val targetPath = Paths.get(targetPaths)
val sourceAsZipFile = ZipFile(sourcePath.toFile())
sourceAsZipFile.extractAll(targetPath.toString())
val serverFile = sourceAsZipFile.fileHeaders.first { it.fileName.contains("server.js") }
val packageJson = sourceAsZipFile.fileHeaders.first { it.fileName.contains("package.json") }
val packageJsonSplits = packageJson.fileName.split("/").toMutableList()
packageJsonSplits.removeAt(packageJsonSplits.lastIndex)
val packageJsonParentLocation = packageJsonSplits.joinToString("/")
npmInstall(socket, "npm install --prefix ${targetPaths}$packageJsonParentLocation/", onExit = {
runningServer(socket, "node ${targetPaths}$serverFile") {
send(socket, "pathserver", "${targetPaths}$serverFile")
runningTest(socket, "${targetPaths}$packageJsonParentLocation") {
send(socket, "update", "Test exit with code: $it")
run("killall node")
if (it == 0) {
send(socket, "update", "Test done!")
} else {
send(socket, "update", "Test failed! Please check manually")
}
}
}
})
}
fun runningTest(socket: WebSocket, targetPaths: String, onExit: (Int) -> Unit = {}) {
send(socket, "update", "Running Test Collections...")
run(
"newman run ${newmanCollectionPath}/collect.json -e ${newmanCollectionPath}/env.json -r json-summary --reporter-summary-json-export ${targetPaths}/report.json",
onExit = { onExitNewMan ->
val path = Paths.get("${targetPaths}/report.json")
val value = Files.readAllLines(path).joinToString("\n")
send(socket, "result", value)
onExit(onExitNewMan)
},
onMessages = {
println(it)
}
)
}
fun runningServer(socket: WebSocket, serverFile: String, onMessages: (String) -> Unit) {
send(socket, "update", "Running server...")
run(serverFile, onMessages = {
onMessages(it)
}, onExit = { onExitServer ->
run("killall node")
send(socket, "update", "Server exit with code: $onExitServer")
})
}
fun npmInstall(socket: WebSocket, projectPath: String, onMessages: (String) -> Unit = {}, onExit: () -> Unit = {}) {
send(socket, "update", "Installing NPM package...")
run(projectPath, onMessages = {
onMessages(it)
}, onExit = {
if (it == 0) {
onExit()
} else {
send(socket, "update", "Installing NPM exit with code: $it")
}
})
}
fun send(socket: WebSocket, type: String, data: String, other: String? = null) {
socket.send(Gson().toJson(IncomingMessage(type, data, other)))
}
fun run(command: String, onMessages: (String) -> Unit = {}, onExit: (Int) -> Unit = {}) {
val process = ProcessBuilder("/bin/sh", "-c", command)
.start()
val streamGobbler = StreamGobbler(process.inputStream) { x: String? ->
if (x != null) {
onMessages(x)
}
}
Executors.newSingleThreadExecutor().submit(streamGobbler)
val exitCode = process.waitFor()
onExit(exitCode)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment