Created
July 8, 2021 06:05
-
-
Save alfianyusufabdullah/fa492fd8789e7d0f9eec9abc4f8e711d to your computer and use it in GitHub Desktop.
playground
This file contains hidden or 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
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!"); | |
}); | |
}) | |
}); |
This file contains hidden or 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
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)) | |
}); |
This file contains hidden or 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
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) | |
} | |
} |
This file contains hidden or 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
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