BAB IV IMPLEMENTASI DAN PENGUJIAN
4.1 Persiapan Lingkungan Kerja Setelah melakukan analisis dan perancangan, tahapan selanjutnya adalah implementasi dan pengujian. Pada tahapan ini dilakukam tahapan persiapan lingkungan kerja yang terdiri dari 3 (tiga) bagian yaitu pemilihan spesifikasi kebutuhan sistem, penyiapan lingkungan kerja pada komputer, penyiapan aplikasi untuk melakukan manajemen kontrol pembuatan aplikasi dan pembuatan issue/task terkait dengan apa saja yang harus dikerjakan untuk menyelesaikan aplikasi ini.
4.2 Implementasi
4.2.1 Implementasi Sistem Kerja Crawler Hubungan di dalam sistem Crawler berbasi Laravel PHP Framework dalam melayani request dapat dilihat pada gambar berikut ini :
Models Routing Controller
Crawler
index.php
Cache
View
Mailer Vendor Queue
Other Package
Gambar 4.1 Hubungan dalam sistem Crawler
55
56 1. File index.php yang terdapat pada “public/index.php” bekerja sebagai pintu gerbang, melakukan utilisasi sumber daya apa yang diperlukan untuk menjalankan framework. 2. File routes.php yang terdapat pada “app/routes.php” mengarahkan HTTP Request sesuai yang terdapat pada file routes.php tersebut. Sebelum permintaan HTTP tersebut di setujui, terkadang di dalam routing table tersebut ada syarat yang harus dipenuhi. Syrarat ini dinamakan filter, dimana rules dapat ditemukan di file “app/filters.php”. 3. Jika sebuah file cache ada, maka dia akan dikirim langsung ke browser. 4. Controller bertugas menjembatani model dan view. Di dalam controller terdapat perintah-perintah untuk melakukan load library dan sumber daya lain yang diperlukan untuk memproses permintaan. 5. Langkah terakhir dari prosesing di atas adalah merender view untuk di tampilkan ke browser. Sebelum view ditampilkan, view tersebut di cache terlebih dahulu sehingga jika ada request tersebut sama.
Dalam melakukan implementasi fungsi pencarian, penulis membuat beberapa kode pustaka / library yang dibuat khusus untuk melakukan pencarian barang pada masing-masing situs jual-beli barang yang akan digunakan dalam aplikasi Agregator Pencarian Barang yang menjadi kode inti dari aplikasi yang dibangun.
Beberapa
/src/Crawler/Search
kode
yang
digunakan
terdapat
pada
direktori
57
Gambar 4.2 Library pencarian barang
1. SearchServiceProvider.php, merupakan class SearchServiceProvider yang bertugas untuk mengidentifikasikan package Crawler\Search ke Laravel. SearchServiceProvider.php
ini
harus
di
registerkan
di
“app/config/app.php” agar dapat digunakan di dalam Laravel. 2. SearchInterfaces.php, merupakan class SearchInterface yang didalamnya terdapat method getList(). Sehingga ketika class baru yang dibuat sebagai compiler
untuk
melakukan
parsing
hasil
pencarian
harus
mengimplementasikan method getList di dalamnya. 3. Search.php, merupakan class Search yang didalamnya terdapat beberapa method dasar dimana method tersebut dapat digunakan kembali oleh class turunan,
seperti
fire(),
boot(),
getStringFromContent()
dan
getDecimalPrice(). Di dalam class ini juga terdapat method abstract dengan visibility private di antaranya getTitle(), getLink(), getPrice dimana method ini harus diimplementasikan di class turunannya. 4. BerniagaSearch.php dan KaskusSearch.php, kedua class ini merupakan class
turunan
dari
Search
dan
merupakan
impelementasi
dari
58
SearchInterface. Dengan membuat kedua buah file ini maka penulis dapat mendapatkan data dari dua buah website yang berbeda, dimana kedua buah wesite tersebut berbeda isi tag htmlnya. 5. SearchHelper.php, merupakan class bantuan. Dalam class ini ada sebuah method dengan nama htmlClean () yang berfungsi menghapus tag html yang di dapat ketikan melakukan crawling. 6. SearchManager, merupakan class yang mengatur resource pencarian apakah menggunakan class KaskusSearch atau BerniagaSearch. 7. SearchFacace.php, merupakan class yang berfungsi untuk membuat shortcut ketika membuat instance object dari class SearchManager.
Cara kerja dari package Search adalah sebagai berikut : Keterangan untuk SearchManager 1. Ketika user melakukan penambahan kata kunci baru, sistem memanggil class SearchManager melalui class SearchFacade dan membuat sebuah obyek
baru
untuk
mendeklarasikan
obyeknya
yang
kemudian
memerintahkan untuk mengambil hasil pencarian, dengan menggunakan method getResult(). 2. Pada method getResult() di SearchManager, sistem melakukan inisialisasi situs mana yang akan dilakukan pencarian serta membuat object baru untuk masing-masing situs yang akan dicari. 3. Sistem memerintahkan object yang telah dibuat pada nomor 2 (dua), untuk melakukaan boot() ke situs masing-masing dan kemudian mengambil hasilnya dengan menggunakan method getData(); 4. Method getData() adalah method yang berfungsi mengambil attribute data yang telah terisi ketika melakukan crawling. 5. Setelah mendapatkan hasilnya pencarian, maka hasil pencarian tersebut dimasukkan ke attribute “$results” dengan menggunakan method setResults(). 6. Langkah terakhir pada method getResult adalah mengembalikan hasil pencarian.
59
Keterangan KaskusSearch dan Search Meneruskan method boot yang dipanggil oleh SearchManager pada nomor (3), penulis berasumsi menggunakan kaskus 1. Karena class KaskusSearch merupakan class turunan maka attribute yang dimiliki oleh class Search diturunkan pada class KaskusSearch. 2. Pada method boot disini melakukan inisialiasi untuk melakukan curl secara keseluruhan sesuai dengan url yang telah diset. Proses curl ini dapat dilihat pada method fire(), apabila proses berhasil maka hasilnya disimpan pada attribute dengan nama content. Method boot ini terdapat pada class Search. 3. Atribute
content
inilah
yang
nantinya
penulis
manipulasi
agar
mendapatkan data yang diinginkan. 4. Masih pada method boot, setelah mendapatkan content hasil curl maka proses selanjutnya adalah melakukan parsing hasil pencarian dengan memanggil
method
getList().
Method
getList()
terdapat
pada
KaskusSearch yang merupakan implementasi dari SearchInterface. 5. Pada method getList(), sistem melakukan parsing untuk mendapatkan title, link, price, date, local dengan menggunakan kaidah dan method yang telah ditentukan kemudian menyimpan hasilnya ke dalam attribute data. Pemanggilan method getList() akan dilakukan secara recursive selama kaidahnya ditemukan.
4.2.2 Implementasi Antarmuka Implementasi antar muka penting untuk dirancang karena harus dibuat menarik dan tidak sukar dalam penggunaanya dan juga pengguna dapat berinteraksi dengan baik berdasarkan sistem yang telah dirancang. Berikut implementasi dari antarmuka sistem yang telah dibangun.
4.2.3 Implementasi Halaman Pendaftaran Pengguna Baru Halaman pendaftaran berguna sebagai halaman untuk melakukan pendaftaran sebagai pengguna baru. Halaman pendaftaran pengguna dapat dilihat pada gambar dibawah ini:
60
Gambar 4.3 Halaman utama dan pendaftaran akun
Ketika pengunjung membuka situs aplikasi, maka router akan meneruskan permintaan ke HomeController dengan method showWelcome().
Kode 4.1 Potongan kode untuk melakukan routing ke HomeController dan signup
Pada method showWelcome terdapat mengecekan, jika pengunjung tersebut belum login maka yang di tampilkan ke layar adalah view.home.index yang didalamnya memuat halaman pendaftaran. Namun jika pengguna tersebut sudah login, maka yang akan ditampilkan adalah halaman view.search.index yang didalamnya memuat daftar pencarian barang dari pengunjung yang telah login tersebut.
61
Kode 4.2 Potongan kode untuk melakukan pengecekan login id)->get(); return View::make('search.index', $data); } } } /* Location: ./app/controllers/HomeController.php */
Kode 4.3 Potongan kode untuk melakukan pendaftaran 'required', 'email' => 'required|unique:users,email', 'password' => 'required' ) );
Pada potongan kode di atas digunakan untuk melakukan pendaftaran pengguna.
Kelas AuthController merupakan kelas yang bertanggungjawab
untung mengatasi segala ketentuan autentikasi user, dimana terdapat beberapa parameter yang dibutuhkan untuk di masukkan oleh user yaitu username, email, dan password.
62
Kode 4.4 Potongan kode untuk melakukan pendaftaran pengguna ke basis data if ($validator->fails()) { return Redirect::to('/')->withErrors($validator); } else { $data = array( 'username' => Input::get('username'), 'email' => Input::get('email'), 'password' => Input::get('password') ); // insert into database for new user // panggil class User yang berada di /models if ($data = User::saveRegister($data)) { $this->mail($data); // return "Signup success"; return Redirect::to('signup/success'); } else { return App::abort(500, 'Internal server error.'); } } }
Setelah mendapatkan masukkan dari pengguna, kode di atas akan melakukan validasi baik username, email, dan password yang di masukkan dengan yang ada di dalam basis data. Jika username dan email belum terdapat pada basis data, maka kemudian kode di atas akan melakukan registrasi pengguna ke basis data.
Kode 4.5 Potongan kode untuk mengirimkan surel verifikasi /** * Send mail verification * * @param array $data * @return mixed */ private function mail($data) { Mail::queue('emails.welcome', ($data) { $m->to($data['email'], >subject('Welcome to Crawler App !'); }); } }
$data,
function($m)
use
$data['username'])-
Setelah melakukan registrasi ke basis data, kode di atas berfungsi untuk melakukan pengiriman surel sebagai bagian dari verifikasi.
Baru kemudian
63
setelah pengguna baru berhasil melakukan mendaftaran, maka sistem akan menampilkan halaman pemberitahuan untuk melakukan konfirmasi alamat surel.
Gambar 4.4. Halaman sukses mendaftar
4.2.4 Implementasi Surel Konfirmasi Pendaftaran Pengguna Baru Berikut ini adalah contoh
isi surel konfirmasi pendaftaran yang di
dalamnya memuat tautan yang beirisi kode aktivasi.
Gambar 4.5. Surel konfirmasi aktivasi akun
64
4.2.5 Implementasi Halaman Konfirmasi Pendaftaran Pengguna Baru Setelah pengguna mengklik tautan yang berasal dari surel yang didalamnya memuat kode verifikasi. Sistem akan melakukan validasi, jika validasi di nyatakan valid maka akan ditampilkan gambar dibawah ini:
Gambar 4.6 Halaman Konfirmasi Aktivasi Akun
4.2.6 Implementasi Halaman Login Sebelum dapat menggunakan layanan sistem Agregator pencarian barang, pengguna yang sudah aktif harus melakukan login terlebih dahulu. Halaman login dapat dilihat pada gambar dibawah ini :
65
Gambar 4.7 Halaman Login
4.2.7 Implementasi Halaman Daftar Kata Kunci Pencarian Pada halaman ini adalah halaman dashboard pengguna yang memuat daftar kata kunci pencarian yang telah dicari. Halaman daftar pencarian kata kunci dapat dilihat pada gambar dibawah ini :
Gambar 4.8 Halaman Kata Kunci Pencarian
66
4.2.8 Implementasi Halaman Tambah Pencarian Pada halaman ini adalah halaman untuk menambah kata kunci pencarian. Pengguna mengisi data yang terdapat di dalam form yang memuat kata kunci pencarian dan ke situs mana sistem akan melakukan pencarian barang.
Gambar 4.9 Halaman Tambah Pencarian
Ketika pengguna ingin membuat kata kunci pencarian baru, maka router akan meneruskan ke CrawlerController dengan method create . Kode 4.6 Potongan kode untuk memanggil halaman pencarian baru
67
Ketika form tersebut di submit maka sistem akan melakukan validasi, jika dinyatakan valid maka sistem akan menyimpan kata kunci pencarian tersebut ke dalam basis data, lalu kemudian menajalan tugas queue, dengan memangil kelas Daemon dengan method crawler.
Kode 4.7 Potongan kode untuk menambah kata kunci pencarian 'required', 'sites' => 'required', ]; $validator = Validator::make(Input::all(), $rules); if ($validator->fails()) { return Redirect::to('/')->withErrors($validator->messages()); } // Insert into search table $data = array( 'name' => Input::get('name'), 'sites' => json_encode(Input::get('sites')), 'user_id' => Auth::user()->id ); Search::create($data); // Set queue Queue::push('Daemon@crawler', array('user_id' => $data['user_id'])); return Redirect::to('/'); } } /* Location : ./app/controllers/CrawlerController */
Kode di atas menjelaskan bahwa dalam melakukan pencarian, terdapat dua hal yang dibutuhkan sebagai syarat untuk dapat melakukan pencarian, yaitu variabel 'name' dan 'sites'. yang kemudian kata kunci pencarian tersebut akan di validasi dan dimasukkan kedalam tabel pencarian pada basis data, dimana dalam tabel pencarian tersebut disimpan nama kata kunci, situs, dan identitas dari pengguna yang melakukan pencarian tersebut.
68
Kode 4.8 Potongan kode untuk melakukan pencarian kata kunci get(); Log::info("Runinng Crawler"); if ( ! $search) { Log::error('Search token is not valid.'); } foreach ($search as $key) { // Crawler started $results = SearchEngine::getResult($key->name, json_decode($key->sites)); //Log::info(json_decode($key->sites)); // Jika hasil crawling ditemukan if (count($results) > 0) { // loop hasil crawling foreach ($results as $result) { // cari link terlebih dahulu $data = Result::where('link', $result['link'])->first(); if ( ! $data) { //Log::info('Insert into result.'); Result::create(array( 'provider' => $result['provider'], 'title' => $result['title'], 'link' => $result['link'], 'price' => $result['price'], 'location' => $result['location'], 'search_id' => $key->id, 'posted_at' => $result['date'] )); } else { // Log::error('Ada link, tidak bisa insert '. json_encode($result)); } }
Kode di atas menjelaskan bahwa class Daemon disini memanggi facade Crawler\Search\SearchFacade yang diberi alias SearchEngine . Pada method crawler di sini melakukan perintah select kata kunci pencarian berdasarkan user_id, dan melakukan looping kata kunci yang telah di masukkan oleh pengguna. SearchEngine dengan method getResult dipanggil untuk melakukan crawling atau pencarian ke situs pasar daring, apabila terdapat hasilnya maka dilakukan penyimpanan ke tabel search result. Akan tetapi sebelum menyimpan
69
data, sistem melakukan pengecekan terlebih dahulu apakah sudah terdapat dalam tabel search result berdasarkan link.
Kode 4.9 Potongan kode untuk melakukan pengiriman surel // Fugsi mailerr $r = DB::table('search_results') ->whereNull('delivery_status') ->where('search_id', $key->id) ->get(); $s = DB::table('search') >join('users','search.user_id','=','users.id') ->where('search.id', $key->id) ->first(array( 'users.username as username', 'users.email as email', 'search.name as search_name' )); if ($r) { Log::info('Try sending email'); Mail::queue('emails.newslatter', array('results' => $r, 'data' => $s) , function($message) use ($s) { $message->to($s->email, $s->username)>subject('Hasil Pencarian Berdasarkan :'.$s->search_name); }); $rs = DB::table('search_results') ->where('search_id', $key->id) ->update(array( 'delivery_status' => '1', 'delivery_at' => date('Y-m-d H:i:s') )); } } else { Log::info('Jobs id : ' . $job->getJobId().' is deleted'); } } $job->release(1); } }
Selanjutnya seperti pada barisan kode di atas adalah fungsi mailer yang akan melakukan pengecekan pada tabel search_result, jika pada tabel search_result dengan user id yang digunakan ditemukan dengan kondisi kolom
70
delivery status sama dengan null, maka data search_result yang bersangkutan akan di kirimkan ke pengguna melalui surel. Jika hasil pembacaan terhadap kolom delivery status pada
tabel
search_result tidak sama dengan null, maka fungsi mailer tidak akan berjalan dan akan memasukkan job atau pekerjaan pencarian kembali ke antrian queue hingga mendapatkan hasil yang berbeda.
4.2.9 Implementasi Surel Notifikasi Berikut adalah surel notifikasi yang diterima oleh pengguna yang telah membuat pencarian brang pada crawler app:
(berlanjut…)
71
(Lanjutan ...)
Gambar 4.10 Surel Notifikasi Pengguna
4.2.10 Implementasi Basis Data Implementasi basis data yang digunakan untuk sistem Agregator pencarian barang menggunakan beberapa table basis data yaitu table users, table search, dan table search_results, dengan keterangan struktur yang dapat dilihat pada Gambar 4.11, Gambar 4.12, dan Gambar 4.13 berikut ini.
72
Gambar 4.11 Struktur tabel users
Gambar 4.12 Struktur tabel search
73
Gambar 4.13 Struktur tabel search_results
4.3
Pengujian Pengujian sistem dilakukan untuk menguji program yang telah dibuat
apakah sudah sesuai dengan rancangan atau tidak. Pengujian yang akan dilakukan yaitu menguji proses penyimpanan konfigurasi, proses pengambilan data produk, serta proses penampilan data produk yang sudah ditarik dan disimpan di dalam basis data Uji coba dilakukan setelah pembuatan perangkat lunak selesai dengan percobaan pada komputer tampilan pengguna. Dengan melakukan uji coba ini dapat dilakukan untuk mengetahui kemungkinan terjadinya kesalahan dan untuk memastikan fungis-fungsi yang terdapat pada modul-modul aplikasi ini apakah sudah berjalan dengan baik. Tahapan pengujian ini meliputi berbagai skenario pengujian, hasil pengujian dan analisis hasil pengujian. Dalam proses pengujiannya metode yang digunakan adalah black box. Metode black box merupakan pengujian dengan metode test dari persfektif eksternal, tidak ada informasi mengenai struktur
74
internal perangkat lunak baik yang berkaitan dengan desain atau listing kode program. Pengujian
ini
bisa
dilakukan
baik
secara
fungsional
maupun
nonfungsional, walaupun pada umumnya yang dilakukan kebanyakan secara fungsional. Pengujian ini dapat dilakukan pada semua level tes. Semakin tinggi level yang diuji, semakin besar keharusan untuk melakukan pengujian menggunakan metode black box. Pengujian tipe ini dapat mendeteksi adanya bagian dari spesifikasi yang diimplementasikan, tetapi tidak bisa mendeteksi keseluruhan kemungkinan kesalahan operasional. Spesifikasi sistem lingkungan pengujian terbagi menjadi 2 (dua) yaitu perangkat keras dan perangkat lunak yang dapat dilihat pada keterangan di bawah ini: 1.
Perangkat Keras a. Prosesor Intel Core i5 2 GHz b. RAM sebesar 2 GB 1333 MHz DDR3 c. Harddisk 20 GB
2.
Perangkat Lunak a. Sistem Operasi Debian 7 b. Web Server, Apache Versi 2.2.22 c. Bahasa Pemrogaman Server Side, PHP Versi 5.4.3 d. Database Server, MySQL Versi 5.5.4.1 e. Text Editor, Notepad++ Versi 6.7.3 f. Aplikasi UML Modeling, StarUML 5.0 g. Beanstalkd & Supervisor h. Twitter Bootstrap CSS i. Laravel 4.0 PHP Framework
75
Hasil dari pengujian aplikasi dapat dilihat pada Tabel 4.1 Hasil Pengujian di bawah ini: Tabel 4.1 Hasil Pengujian (berlanjut ...) No
1
2
2
3
Deskripsi Mendaftar menjadi pengguna baru
Aktivasi akun
Halaman login
Halaman logout
Sifat
Kondisi Awal
Hasil yang diinginkan
Normal : menampilkan halaman pendaftaran Tidak Normal : tidak dapat menampilkan halaman pengguna baru Normal : menampilkan halaman akun berhasil di aktivasi Tidak Normal : tidak dapat menampilkan halaman akun berhasil di aktivasi Normal: menampilkan halaman login Tidak Normal: tidak bisa menampilkan halaman login
Menampilkan halaman pendaftaran pengguna baru Tidak dapat menampilkan halaman pendaftaran pengguna baru
Normal: keluar dari sistem
Menampilkan halaman logout
Tidak Normal: tidak bisa keluar dari sistem
Tidak bisa menampilkan halaman logout
Gagal masuk keluar dari aplikasi
Menu pencarian barang
Menampilkan halaman pencarian barang
Menu pencarian barang tidak tampil
Tidak bisa menampilkan menu pencarian barang
Menu pencarian barang
Menampilkan halaman pencarian barang
Menampilkan halaman aktivasi akun
Halaman pendaftarann ditampilkan
Hasil Pengujian
Normal
Halaman pendaftarann tidak ditampilkan Akun berhasil di aktivasi dan halaman aktivasi akun ditampilkan Normal
Tidak dapat menampilkan halaman pendaftaran pengguna baru
Gagal aktivasi dan halaman aktivasi tidak ditampilkan
Menampilkan halaman login
Masuk ke dalam aplikasi
Tidak bisa menampilkan halaman login
Gagal masuk ke dalam aplikasi
Normal
Keluar dari aplikasi Normal
4
5
Menu Pencarian Barang
Menu Hasil Pencarian
Normal : dapat menampilkan menu pencarian barang Tidak Normal : tidak dapat menampilkan menu pencarian barang Normal : dapat menampilkan menu hasil pencarian barang
Normal
Normal
76
(Tabel 4.1 Lanjutan ...) Tidak Normal : tidak dapat menampilkan menu hasil pencarian barang 6
Surel Hasil Pencarian Barang
Normal : Surel diterima pengguna Tidak Normal : Surel tidak diterima pengguna
Menu hasil pencarian barang tidak tampil Surel hasil pencarian diterima pengguna Surel hasil pencarian tidak diterima pengguna
Tidak bisa menampilkan menu hasil pencarian barang Surel hasil pencarian berhasil diterima pengguna Normal Surel hasil pencarian tidak diterima pengguna
Dalam pengujian blackbox berdasarkan tabel pengujian di atas, didapati bahwa setiap skenario dapat berjalan dengan sifat normal atau sesuai dengan yang diharapkan. Sehingga dapat disimpulkan bahwa dalam pengujian blackbox ini tidak didapati malfungsi atau kondisi yang tidak normal. Namun perlu di ingat bahwasannya
pengujian
blackbox
tidak
dapat
mendeteksi
keseluruhan
kemungkinan kesalahan yang dapat terjadi di luar skenario pengujian di atas.
4.4
Analisis Hasil Pengujian Dari keseluruhan proses pengujian dapat dianalisis bahwa:
1.
Aplikasi ini dapat terkoneksi dengan database dimana tidak ada kesalahan dalam proses pengambilan dan menampilkan data. Hal ini terlihat ketika dalam aplikasi mengambil data dari basis data, data yang ada pada basis data tersebut dapat ditampilkan sesuai dengan perintah yang ada dalam aplikasi ini.
2.
Pengguna dapat melakukan pendaftaran akun karena proses masukkan dari pengguna dapat di terima dan di proses ke dalam basis data.
3.
Pengguna menerima surel aktivasi akun, dikarenakan proses pendaftaran berhasil dan perintah untuk melakukan pengiriman surel oleh aplikasi sukses di eksekusi, sehingga surel aktivasi akun dari sistem dapat diterima pengguna.
4.
Pengguna dapat melakukan aktivasi karena sistem mengirimkan tautan aktivasi user yang valid kepada pengguna sehingga saat penggunna menuju
77
tautan yang dikirim, sistem dapat menerima dengan baik dan dapat merubah status aktivasi pengguna pada basis data. 5.
Pengguna yang sudah melakukan aktivasi dapat login dengan alamat surel dan password yang telah dibuat sebelumnya, karena alamat surel yang digunakan dan kata sandi atau password yang telah di buat sudah menjadi aktif saat pengguna mengakses tautan aktivasi akun yang dikirimkan melalui surel.
6.
Pengguna dapat membuat pencarian berdasakan kata kunci, karena pengguna melakukan pencarian berdasarkan kata kunci dan juga memilih salah satu atau lebih opsi pasar daring yang diberikan.
7.
Pengguna dapat membuat pencarian berdasarkan kata kunci dan lokasi karena pengguna juga melakukan pemilihan opsi pasar daring dan pilihan lokasi yang diberikan.
8.
Pengguna dapat membuat pencarian berdasarkan kata kunci dan harga minimum karena pengguna juga melakukan pemilihan opsi pasar daring dan mengisi formulir harga minimum yang diberikan.
9.
Pengguna dapat membuat pencarian berdasarkan kata kunci dan harga maksimum karena pengguna melakukan pemilihan kata kunci, opsi pasar daring dan mengisi kolom harga maksimum yang diberikan.
10.
Pengguna dapat membuat pencarian berdasarkan kata kunci dan harga minimum dan maksimum karena pengguna melakukan pemilihan kata kunci, opsi pasar daring dan mengisi kolom harga minimum dan maksimum yang diberikan.
11.
Pengguna dapat membuat pencarian berdasarkan kata kunci, harga minimum dan maksimum, serta lokasi. karena pengguna melakukan pemilihan kata kunci, opsi pasar daring dan mengisi kolom harga minimum dan maksimum, serta opsi lokasi yang diberikan