{"id":13708021,"url":"https://github.com/dineshsonachalam/tech-courses-search-engine","last_synced_at":"2026-03-08T23:08:16.923Z","repository":{"id":37609180,"uuid":"164276291","full_name":"dineshsonachalam/tech-courses-search-engine","owner":"dineshsonachalam","description":"A real-time tech course finder, created using Elasticsearch, Python, React+Redux, Docker, and Kubernetes.","archived":false,"fork":false,"pushed_at":"2026-01-12T08:35:51.000Z","size":10168,"stargazers_count":146,"open_issues_count":18,"forks_count":41,"subscribers_count":6,"default_branch":"master","last_synced_at":"2026-01-12T18:24:24.463Z","etag":null,"topics":["api-testing","ci-cd","cypressjs","elasticsearch-queries","github-action","kubernetes","nginx","nginx-proxy","pytest","python-3","react","redux","tutorial"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dineshsonachalam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"License","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-01-06T04:49:28.000Z","updated_at":"2025-10-06T09:26:27.000Z","dependencies_parsed_at":"2022-08-08T21:01:03.756Z","dependency_job_id":"777a3ada-540c-4d01-b011-12ee7c293bd0","html_url":"https://github.com/dineshsonachalam/tech-courses-search-engine","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/dineshsonachalam/tech-courses-search-engine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dineshsonachalam%2Ftech-courses-search-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dineshsonachalam%2Ftech-courses-search-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dineshsonachalam%2Ftech-courses-search-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dineshsonachalam%2Ftech-courses-search-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dineshsonachalam","download_url":"https://codeload.github.com/dineshsonachalam/tech-courses-search-engine/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dineshsonachalam%2Ftech-courses-search-engine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30276607,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T20:45:49.896Z","status":"ssl_error","status_checked_at":"2026-03-08T20:45:49.525Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-testing","ci-cd","cypressjs","elasticsearch-queries","github-action","kubernetes","nginx","nginx-proxy","pytest","python-3","react","redux","tutorial"],"created_at":"2024-08-02T22:01:53.308Z","updated_at":"2026-03-08T23:08:16.906Z","avatar_url":"https://github.com/dineshsonachalam.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"\u003ca href=\"https://search.dineshsonachalam.com\"\u003e\n    \u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://i.imgur.com/j0ZQqwV.png\" alt=\"SearchEngine\"\u003e\n    \u003c/p\u003e\n\u003c/a\u003e\n\u003cp align=\"center\"\u003e\n    \u003cem\u003ePowered by ElasticSearch, Python, React, Redux, Kubernetes, Cypress E2E, Pytest and Github CI/CD\u003c/em\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://sonarcloud.io/dashboard?id=tech-courses-search-engine\"\u003e\n        \u003cimg src=\"https://sonarcloud.io/api/project_badges/quality_gate?project=tech-courses-search-engine\"/\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\u003cp  align=\"center\"\u003e\n  \u003ca href=\"https://www.codacy.com/gh/dineshsonachalam/tech-courses-search-engine/dashboard?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=dineshsonachalam/tech-courses-search-engine\u0026amp;utm_campaign=Badge_Grade\"\u003e\n        \u003cimg src=\"https://app.codacy.com/project/badge/Grade/978c48d5a7ae4b28a1b17df88b6f1d0e\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/dineshsonachalam/tech-courses-search-engine/actions\" alt=\"CI/CD status\"\u003e\n      \u003cimg src=\"https://github.com/dineshsonachalam/tech-courses-search-engine/actions/workflows/k8-deploy.yml/badge.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.python.org/downloads/release/python-390/\" alt=\"Python 3.9\"\u003e\n      \u003cimg src=\"https://img.shields.io/badge/python-3.9-blue.svg\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/repository/docker/dineshsonachalam/tech-courses-search-engine-backend\" alt=\"Docker pulls\"\u003e\n      \u003cimg src=\"https://img.shields.io/docker/pulls/dineshsonachalam/tech-courses-search-engine-backend.svg\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\u003cp  align=\"center\"\u003e\n    \n## Demo\n1. \u003ca href=\"https://search.dineshsonachalam.com/\"\u003eLive demo\u003c/a\u003e  \n2. \u003ca href=\"https://vimeo.com/589852893\"\u003eVideo demo\u003c/a\u003e \n\n## What's this project all about?\n\nThis project showcases how to build real-time search engines like Google, Coursera, Medium, etc. We focus on the following aspects as part of this project.\n\n- [x] [1. Understanding all significant components in ElasticSearch and its Auto completion feature.](#1-understanding-all-significant-components-in-elasticsearch-and-its-auto-completion-feature)\n- [x] [2. Building an API service that interacts with ElasticSearch to be used by the UI.](#2-building-an-api-service-that-interacts-with-elasticsearch-to-be-used-by-the-ui)\n- [x] [3. Testing API using Pytest.](#3-testing-api-using-pytest)\n- [x] [4. Building UI using React and Redux.](#4-building-ui-using-react-and-redux)\n- [x] [5. Testing UI using Cypress.](#5-testing-ui-using-cypress)\n\n## Application Architecture\n\n\u003cimg src=\"https://user-images.githubusercontent.com/12673979/117518002-c0017c00-afbb-11eb-97f3-14c253cad321.png\"/\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/12673979/117521109-ae26d580-afc9-11eb-8dbd-663eeabaf0ff.png\"/\u003e\n\n## 1. Understanding all significant components in ElasticSearch and it's Auto completion feature.\n\n**What is ElasticSearch?**\n\nFree and Open, Distributed, RESTful Search Engine. You can use Elasticsearch to store, search, and manage data for:\n\n- Logs\n- Metrics\n- A search backend\n- Application monitoring\n- Endpoint security\n\nHow does Elasticsearch work?\n\nLet's understand some basic components of how it organizes data in ElasticSearch.\n\n**Logical components**\n\n1. Documents:\n\nDocuments are the low level unit of information that can be indexed in Elasticsearch expressed in JSON, which is the global internet data interchange format. You can think of a document like a row in a relational database, representing a given entity — the thing you’re searching for. In Elasticsearch, a document can be more than just text, it can be any structured data encoded in JSON. That data can be things like numbers, strings, and dates. Each document has a unique ID and a given data type, which describes what kind of entity the document is. For example, a document can represent an encyclopedia article or log entries from a web server.\n\n2. Indices:\n\nAn index is a collection of documents that have similar characteristics. An index is the highest level entity that you can query against in Elasticsearch. You can think of the index as being similar to a database in a relational database schema. Any documents in an index are typically logically related. In the context of an e-commerce website, for example, you can have an index for Customers, one for Products, one for Orders, and so on. An index is identified by a name that is used to refer to the index while performing indexing, search, update, and delete operations against the documents in it.\n\n3. Index templates:\n\nAn index template is a way to tell Elasticsearch how to configure an index when it is created. The template is applied automatically whenever a new index is created with the matching pattern.\n\n**Backend components**\n\n1. Cluster:\n\nAn Elasticsearch cluster is a group of one or more node instances that are connected together. \n\n2. Node:\n\nA node is a single server that is a part of a cluster. A node stores data and participates in the cluster’s indexing and search capabilities. An Elasticsearch node can be configured in different ways:\n\n(i) Master Node — Controls the Elasticsearch cluster and is responsible for all cluster-wide operations like creating/deleting an index and adding/removing nodes.\n\n(ii) Data Node — Stores data and executes data-related operations such as search and aggregation.\n\n(iii) Client Node — Forwards cluster requests to the master node and data-related requests to data nodes.\n\n3. Shards:\n\nElasticsearch provides the ability to subdivide the index into multiple pieces called shards. Each shard is in itself a fully-functional and independent “index” that can be hosted on any node within a cluster. By distributing the documents in an index across multiple shards, and distributing those shards across multiple nodes, Elasticsearch can ensure redundancy, which both protects against hardware failures and increases query capacity as nodes are added to a cluster.\n\n4. Replicas: \n\nElasticsearch allows you to make one or more copies of your index’s shards which are called replica shards or just replicas.\n\n**How to implement Autocompletion ElasticSearch feature?**\n\n1. Start ElasticSearch Docker container\n```\nmkdir -p ES_DATA \u0026\u0026 docker run -v $(pwd)/ES_DATA:/usr/share/elasticsearch/data -e \"discovery.type=single-node\" -e \"ES_JAVA_OPTS=-Xms750m -Xmx750m\" -p 9200:9200 elasticsearch:7.12.0 \n```\n\n2. Verify the health status of your cluster.\n```\ndineshsonachalam@macbook ~ % curl --location --request GET 'http://elasticsearch:9200/_cat/health'\n1629473241 15:27:21 docker-cluster green 1 1 0 0 0 0 0 0 - 100.0%\n```\n\n3. Create an index template that contains the following properties topic, title, URL, labels, and upvotes.\n```\ncurl -X PUT \"elasticsearch:9200/_index_template/template_1?pretty\" -H 'Content-Type: application/json' \\\n-d'{\n    \"index_patterns\": \"cs.stanford\",\n    \"template\": {\n        \"settings\": {\n            \"number_of_shards\": 1\n        },\n        \"mappings\": {\n            \"_source\": {\n                \"enabled\": true\n            },\n            \"properties\": {\n                \"topic\": {\n                    \"type\": \"text\"\n                },\n                \"title\": {\n                    \"type\": \"completion\"\n                },\n                \"url\": {\n                    \"type\": \"text\"\n                },\n                \"labels\": {\n                    \"type\": \"text\"\n                },\n                \"upvotes\": {\n                    \"type\": \"integer\"\n                }\n            }\n        }\n    }\n}'\n```\n\n4. Validate if the index template is available.\n```\ndineshsonachalam@macbook ~ % curl --location --request GET 'http://elasticsearch:9200/_index_template/template_1'\n{\n    \"index_templates\": [\n        {\n            \"name\": \"template_1\",\n            \"index_template\": {\n                \"index_patterns\": [\n                    \"cs.stanford\"\n                ],\n                \"template\": {\n                    \"settings\": {\n                        \"index\": {\n                            \"number_of_shards\": \"1\"\n                        }\n                    },\n                    \"mappings\": {\n                        \"_source\": {\n                            \"enabled\": true\n                        },\n                        \"properties\": {\n                            \"upvotes\": {\n                                \"type\": \"integer\"\n                            },\n                            \"topic\": {\n                                \"type\": \"text\"\n                            },\n                            \"title\": {\n                                \"type\": \"completion\"\n                            },\n                            \"url\": {\n                                \"type\": \"text\"\n                            },\n                            \"labels\": {\n                                \"type\": \"text\"\n                            }\n                        }\n                    }\n                },\n                \"composed_of\": []\n            }\n        }\n    ]\n}\n```\n\n5. Create a new index called cs.stanford\n```\ndineshsonachalam@macbook ~ % curl --location --request PUT 'http://elasticsearch:9200/cs.stanford/'\n{\n    \"acknowledged\": true,\n    \"shards_acknowledged\": true,\n    \"index\": \"cs.stanford\"\n}\n```\n\n6. Validate if the cs.stanford index is available.\n```\ndineshsonachalam@macbook ~ % curl --location --request GET 'http://elasticsearch:9200/cs.stanford/'\n{\n    \"cs.stanford\": {\n        \"aliases\": {},\n        \"mappings\": {\n            \"properties\": {\n                \"labels\": {\n                    \"type\": \"text\"\n                },\n                \"title\": {\n                    \"type\": \"completion\",\n                    \"analyzer\": \"simple\",\n                    \"preserve_separators\": true,\n                    \"preserve_position_increments\": true,\n                    \"max_input_length\": 50\n                },\n                \"topic\": {\n                    \"type\": \"text\"\n                },\n                \"upvotes\": {\n                    \"type\": \"integer\"\n                },\n                \"url\": {\n                    \"type\": \"text\"\n                }\n            }\n        },\n        \"settings\": {\n            \"index\": {\n                \"routing\": {\n                    \"allocation\": {\n                        \"include\": {\n                            \"_tier_preference\": \"data_content\"\n                        }\n                    }\n                },\n                \"number_of_shards\": \"1\",\n                \"provided_name\": \"cs.stanford\",\n                \"creation_date\": \"1629526849180\",\n                \"number_of_replicas\": \"1\",\n                \"uuid\": \"NrvQ6juOSNmf0GOPO2QADA\",\n                \"version\": {\n                    \"created\": \"7120099\"\n                }\n            }\n        }\n    }\n}\n```\n\n7. Add documents to cs.stanford index.\n```\ncd backend \u0026\u0026 python -c 'from utils.elasticsearch import Elasticsearch; es = Elasticsearch(\"cs.stanford\"); es.add_documents()' \u0026\u0026 cd ..\n```\n\n8. Get the total count of the documents in cs.stanford index. We can able to see that the document count is 1350.\n```\ndineshsonachalam@macbook tech-courses-search-engine % curl --location --request GET 'http://elasticsearch:9200/cs.stanford/_count'\n{\n    \"count\": 1350,\n    \"_shards\": {\n        \"total\": 1,\n        \"successful\": 1,\n        \"skipped\": 0,\n        \"failed\": 0\n    }\n}\n```\n\n9. Use ElasticSearch suggesters search for autocompletion. The suggest feature suggests similar looking terms based on a provided text by using a suggester.\n\n```\ndineshsonachalam@macbook tech-courses-search-engine % cd backend \u0026\u0026 python -c 'from utils.filters import SearchFilters; search = SearchFilters(\"cs.stanford\"); print(search.autocomplete(query=\"python\"))' \u0026\u0026 cd ..\n[\n    {\n        \"id\": 1,\n        \"value\": \"Python Data Science Handbook\"\n    },\n    {\n        \"id\": 2,\n        \"value\": \"Python Game Programming Tutorial: SpaceWar\"\n    },\n    {\n        \"id\": 3,\n        \"value\": \"Python for Beginners - Learn Python Programming La\"\n    },\n    {\n        \"id\": 4,\n        \"value\": \"Python for Data Science and Machine Learning Bootc\"\n    },\n    {\n        \"id\": 5,\n        \"value\": \"Python for Security Professionals\"\n    }\n]\n```\n\n## 2. Building an API service that interacts with ElasticSearch to be used by the UI.\n\n1. Start the ElasticSearch, Backend and Frontend services\n```\nsh dev-startup.sh\n```\n\n2. API Documentation\n\n#### ElasticSearch Autocomplete\n\n```http\n  GET /autocomplete\n```\n\n| Parameter | Type     | Description                |\n| :-------- | :------- | :------------------------- |\n| `query` | `string`   | **Required**. Query string |\n\n**Sample response**\n```\ndineshsonachalam@macbook ~ % curl --location --request GET 'elasticsearch:8000/autocomplete?query=python'\n[\n    {\n        \"id\": 1,\n        \"value\": \"Python Data Science Handbook\"\n    },\n    {\n        \"id\": 2,\n        \"value\": \"Python GUI with Tkinter Playlist\"\n    },\n    {\n        \"id\": 3,\n        \"value\": \"Python Game Programming Tutorial: SpaceWar\"\n    },\n    {\n        \"id\": 4,\n        \"value\": \"Python PostgreSQL Tutorial Using Psycopg2\"\n    },\n    {\n        \"id\": 5,\n        \"value\": \"Python Programming for the Raspberry Pi\"\n    }\n]\n```\n\n\n#### Query Search\n\n```http\n  POST /string-query-search\n```\n\n| Parameter | Type     | Description                |\n| :-------- | :------- | :------------------------- |\n| `query` | `string`   | **Required**. Query string |\n\n**Sample response**\n```\ndineshsonachalam@macbook ~ % curl --location --request POST 'elasticsearch:8000/string-query-search?query=python'\n[\n    {\n        \"id\": 1,\n        \"title\": \"Google's Python Class\",\n        \"topic\": \"Python\",\n        \"url\": \"https://developers.google.com/edu/python/\",\n        \"labels\": [\n            \"Free\",\n            \"Python 2\"\n        ],\n        \"upvotes\": 213\n    },\n    {\n        \"id\": 2,\n        \"title\": \"Complete Python Bootcamp\",\n        \"topic\": \"Python\",\n        \"url\": \"https://click.linksynergy.com/deeplink?id=jU79Zysihs4\u0026mid=39197\u0026murl=https://www.udemy.com/complete-python-bootcamp\",\n        \"labels\": [\n            \"Paid\",\n            \"Video\",\n            \"Beginner\",\n            \"Python 3\"\n        ],\n        \"upvotes\": 196\n    },\n    {\n        \"id\": 3,\n        \"title\": \"Automate the Boring Stuff with Python\",\n        \"topic\": \"Python\",\n        \"url\": \"http://automatetheboringstuff.com/\",\n        \"labels\": [\n            \"Free\",\n            \"Book\"\n        ],\n        \"upvotes\": 93\n    },\n    {\n        \"id\": 4,\n        \"title\": \"Official Python Tutorial\",\n        \"topic\": \"Python\",\n        \"url\": \"https://docs.python.org/3/tutorial/index.html\",\n        \"labels\": [\n            \"Free\"\n        ],\n        \"upvotes\": 74\n    },\n    {\n        \"id\": 5,\n        \"title\": \"Working with Strings in Python\",\n        \"topic\": \"Python\",\n        \"url\": \"https://academy.vertabelo.com/course/python-strings\",\n        \"labels\": [\n            \"Free\",\n            \"Beginner\",\n            \"Python 3\"\n        ],\n        \"upvotes\": 4\n    },\n    {\n        \"id\": 6,\n        \"title\": \"Learn Python the Hard Way\",\n        \"topic\": \"Python\",\n        \"url\": \"https://learnpythonthehardway.org/book/\",\n        \"labels\": [\n            \"Paid\",\n            \"Book\",\n            \"Python 3\"\n        ],\n        \"upvotes\": 293\n    },\n    {\n        \"id\": 7,\n        \"title\": \"Python for Beginners - Learn Python Programming Language in 2 Hours\",\n        \"topic\": \"Python\",\n        \"url\": \"https://www.youtube.com/watch?v=yE9v9rt6ziw\",\n        \"labels\": [\n            \"Free\",\n            \"Video\",\n            \"Beginner\",\n            \"Python 3\"\n        ],\n        \"upvotes\": 62\n    },\n    {\n        \"id\": 8,\n        \"title\": \"Automate the Boring Stuff with Python\",\n        \"topic\": \"Python\",\n        \"url\": \"https://click.linksynergy.com/deeplink?id=jU79Zysihs4\u0026mid=39197\u0026murl=https://www.udemy.com/automate/\",\n        \"labels\": [\n            \"Paid\",\n            \"Video\",\n            \"Beginner\"\n        ],\n        \"upvotes\": 45\n    },\n    {\n        \"id\": 9,\n        \"title\": \"Introduction to Programming with Python\",\n        \"topic\": \"Python\",\n        \"url\": \"https://mva.microsoft.com/en-US/training-courses/introduction-to-programming-with-python-8360\",\n        \"labels\": [\n            \"Free\",\n            \"Video\"\n        ],\n        \"upvotes\": 41\n    },\n    {\n        \"id\": 10,\n        \"title\": \"A Byte of Python\",\n        \"topic\": \"Python\",\n        \"url\": \"http://www.swaroopch.com/notes/python/\",\n        \"labels\": [\n            \"Free\"\n        ],\n        \"upvotes\": 22\n    }\n]\n```\n\n## 3. Testing API using Pytest\n\nPytest is a testing framework based on python. It is mainly used to write API based test cases. Here we are going to test our two API's (autocomplete and string-query-search).\n\n**Start Pytest:**\n```\ndineshsonachalam@macbook tech-courses-search-engine % pytest backend\n=========================================== test session starts ===========================================\nplatform darwin -- Python 3.9.5, pytest-6.2.4, py-1.10.0, pluggy-0.13.1\nrootdir: /Users/dineshsonachalam/Desktop/tech-courses-search-engine\nplugins: cov-2.12.1, metadata-1.11.0\ncollected 2 items                                                                                         \n\nbackend/tests/test_api.py ..                                                                        [100%]\n\n============================================ 2 passed in 0.35s ============================================\ndineshsonachalam@macbook tech-courses-search-engine % \n```\n\n## 4. Building UI using React and Redux.\n\n**What is React?**\n\nA declarative, efficient, and flexible JavaScript library for building user interfaces.\n\n**What is Redux?**\n\nRedux is a JS library for managing client data in applications. Redux allow your state to be available in one place. It is used to manage data in your application.\n\nThings to care about when using redux:\n1. Identify the state.\n2. Write good reducers.\n3. Let's redux state handle the rest.\n\n**Building Parts of redux:**\n\n1. Action -\u003e Action have a type field that tells what kind of action to perform and all other fields contain information or data.\n2. Reducer -\u003e They are functions that take the (current state and action) and return the new state and tell the store how to do.\n3. Store -\u003e The store is the object which holds state of the application.\n\n\u003cimg src=\"https://i.imgur.com/G45gjRr.png\"/\u003e\n\n**React components used in our application:**\n\n**What are React components?**\n\nComponents are independent and reusable bits of code. They serve the same purpose as JavaScript functions, but work in isolation and return HTML via a render() function.\n\nComponents are classified into two types, Class components and Function components.\n\n**What's the difference between class vs functional components:**\n\nIn class component, we can access the value of the state by using this.state inside JSX and we would use setState to update the value of the state. You can set the function inside the event or outside of the render() method -- for readability.\n\nIn functional component, we would use useState to assign initial state and we would use setCount (in our example) to update the state. If we want to access the value of the state, we can omit this.state and call the name of the state instead, in our case, it would just be count.\n\n\n**React components used in our application:**\n\nHere all our React components are available in the **src/components** folder.\n\n```\ndineshsonachalam@macbook frontend % tree src/components \nsrc/components\n├── Nav.js\n├── ResponsiveAntMenu.js\n├── SearchBar.js\n└── SearchResults.js\n\n0 directories, 4 files\n```\n\u003cimg src=\"https://i.imgur.com/eYefwnE.png\"/\u003e\n\n**How Redux is integrated into this React application:**\n\nHere all our Redux components are available in the **src/redux** folder. Here we intialized Actions, Search Reducer and Redux store.\n\n```\ndineshsonachalam@macbook frontend % tree src/redux \nsrc/redux\n├── actionTypes.js\n├── actions.js\n├── reducers\n│   ├── index.js\n│   └── searchReducer.js\n└── store.js\n\n1 directory, 5 files\n```\n\n**To start the UI in development mode:**\n```\nnpm i \u0026\u0026 npm run start --prefix frontend\n```\n\n## 5. Testing UI using Cypress.\n\n**What is Cypress?**\n\nFast, easy and reliable testing for anything that runs in a browser. Cypress is the most popular choice for Integration testing for web applications.\n\n**Cypress Features**\n\n- Test runner: So hands down one of the best features about Cypress is its test runner. It provides a whole new experience to end-to-end testing.\n- Setting up tests: Another great feature that we talked about already is setting up tests are extremely easy, you just install Cypress and then everything gets set up for you\n- Automatic waits – you will barely have to use waits when using Cypress\n- Stubbing – you can easily stub application function behavior and server response.\n\n**Running Cypress Integration test**\n\nThe cypress integration tests for our application is available at frontend/cypress/integration/search-courses.spec.js filepath.\n\n```\ndineshsonachalam@macbook tech-courses-search-engine % tree frontend/cypress\nfrontend/cypress\n├── fixtures\n│   └── example.json\n├── integration\n│   └── search-courses.spec.js\n├── plugins\n│   └── index.js\n└── support\n    ├── commands.js\n    └── index.js\n\n4 directories, 5 files\ndineshsonachalam@macbook tech-courses-search-engine % \n```\n\n**Running your Cypress Test in the Cypress Test Runner:**\n\nTo open the Cypress Test Runner, you can execute the following command below:\n```\nnpx cypress open\n```\n\nOnce the Cypress Test Runner opens up, you can execute your test which will show results similar to this below:\n\nYou can see all the Cypress commands listed below such as visit, URL \u0026 title\nAll your successful assertions will show in Green and failed assertions in Red.\n\n\u003cimg src=\"https://i.imgur.com/F97ooaD.png\"/\u003e\n\u003cimg src=\"https://i.imgur.com/jfmBLuk.png\"/\u003e\n\n## License\n\n[MIT](https://choosealicense.com/licenses/mit/) © [dineshsonachalam](https://www.github.com/dineshsonachalam)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdineshsonachalam%2Ftech-courses-search-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdineshsonachalam%2Ftech-courses-search-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdineshsonachalam%2Ftech-courses-search-engine/lists"}