/gemini-AI-chatbot

Web application that allows users to interact with an AI chatbot powered by Gemini (Google's Generative AI).

Primary LanguageJavaScript

๐Ÿค–๐Ÿ’ฌ Gemini AI Chatbot

๐Ÿ‘‹ Introduction

Welcome to the Gemini AI Chatbot! This application allows users to interact with an AI chatbot using natural language. Built with React, Node, Express, and Gemini (Google's Generative AI), it offers a seamless experience for engaging in conversations with an intelligent virtual assistant.

โญ Features

  • ๐Ÿ” User Authentication: Users can create an account or log in securely using a Google account. Please note that only Google login works currently.
  • ๐Ÿ’ฌ Real-time Messaging: Users can engage in real-time conversations with the AI chatbot, receiving instant responses to their queries.
  • ๐Ÿค– AI-powered Responses: The chatbot utilizes Google's Generative AI technology to generate intelligent responses based on user input.
  • ๐Ÿ”’ Secure Communication: All user interactions are encrypted to ensure privacy and security.
  • ๐ŸŒ Multi-platform Compatibility: The application is compatible across various platforms, including web browsers and mobile devices.
  • โš™๏ธ Customizable Settings: Users can personalize their chat experience by adjusting settings such as language preferences and conversation themes.

๐Ÿ–ผ๏ธ Preview

Landing page

Login page

Messaging page

๐Ÿš€ Getting Started

  1. Clone the repository: git clone https://github.com/xsarahyu/gemini-AI-chatbot.git
  2. Navigate to the backend directory: cd backend
  3. Create an .env file with your Gemini API information:
    clientID={your clientID}
    clientSecret={your clientSecret}
    secret={your secret}
    PORT=8420
    geminiKey={your geminiKey}
    
  4. Install backend dependencies: npm install
  5. Run the backend: node server
  6. Navigate to the frontend directory (in a new terminal): cd app
  7. Install frontend dependencies: npm install
  8. Run the frontend: npm run dev
  9. The app is now live at http://localhost:5173!

๐Ÿ—‚๏ธ File Structure

app/src
โ”œโ”€โ”€ components
โ”‚   โ”œโ”€โ”€ Footer.jsx
โ”‚   โ”œโ”€โ”€ LandingPage.jsx
โ”‚   โ”œโ”€โ”€ LoginPage.jsx
โ”‚   โ”œโ”€โ”€ MessagesComponent.jsx
โ”‚   โ””โ”€โ”€ NavBar.jsx
โ”œโ”€โ”€ App.css
โ”œโ”€โ”€ App.jsx
โ”œโ”€โ”€ index.css
โ””โ”€โ”€ main.jsx
backend
โ””โ”€โ”€ server.js



๐Ÿงช Testing

Unit Tests โ€” Using Jest

To run Jest tests locally:

  1. Navigate to the frotnend directory: cd app
  2. Install frontend dependencies: npm install
  3. Run the tests: npm test
  4. You should now see test coverage in your terminal.

๐Ÿ‘‰ Footer component

Test #1: Ensures that the Footer component renders with the text "Resilient Coders".

describe('Footer component', () => {
test('Renders Footer content', () => {
render(<Footer />)
const footerContent = screen.getByText(/Resilient Coders/)
expect(footerContent).toBeInTheDocument()
})
})

๐Ÿ‘‰ LandingPage component

Test #1: Verifies that the LandingPage component renders with the welcome message.

describe('LandingPage component', () => {
test('Renders LandingPage content', () => {
render(<LandingPage />)
const welcomeContent = screen.getByText(/Welcome to the Resilient Coders AI ChatBot!/i)
expect(welcomeContent).toBeInTheDocument()
})
})

๐Ÿ‘‰ LoginPage component

Test #1: Ensures that the LoginPage component renders with the username input field.

test('Renders username input', () => {
const { getByTestId } = renderedComponent;
const username = getByTestId('username');
expect(username).toBeInTheDocument();
});

Test #2: LoginPage renders with the password input field.

test('Renders password input', () => {
const { getByTestId } = renderedComponent;
const password = getByTestId('password');
expect(password).toBeInTheDocument();
});

Test #3: LoginPage renders with the regular login button.

test('Renders login button', () => {
const { getByTestId } = renderedComponent;
const loginButton = getByTestId('loginButton');
expect(loginButton).toBeInTheDocument();
});

Test #4: LoginPage renders with the Google login button.

test('Renders Google login button', () => {
const { getByTestId } = renderedComponent;
const googleLoginButton = getByTestId('googleLoginButton');
expect(googleLoginButton).toBeInTheDocument();
});

๐Ÿ‘‰ MessagesComponent

Test #1: Simulates entering text into the message input field, clicking the send button, and then verifies that the entered message renders.

test('Renders Message content', () => {
const { getByTestId, getByText } = render(<MessagesComponent />)
const inputField = getByTestId('messageInput')
fireEvent.change(inputField, { target: { value: 'hello' } })
const sendButton = getByTestId('submitMessageButton')
fireEvent.click(sendButton)
const messageContent = getByText("hello")
expect(messageContent).toBeInTheDocument()
}),

Test #2: Ensures that the message input field exists.

test('Message input exists', () => {
const { getByPlaceholderText } = render(<MessagesComponent />)
const inputPlaceholder = getByPlaceholderText('Type your message here...')
expect(inputPlaceholder).toBeInTheDocument()
}),

Test #3: Confirms the existence of the button to send a message.

test('Button to send message exists', () => {
const { getByTestId } = render(<MessagesComponent />)
const submitBtn = getByTestId('submitMessageButton')
expect(submitBtn).toBeInTheDocument()
})

๐Ÿ‘‰ NavBar component

Test #1: Verifies that the NavBar renders with the "Home" and "Login" links.

describe('NavBar component', () => {
test('Renders NavBar', () => {
const { getByTestId } = render(
<BrowserRouter>
<NavBar />
</BrowserRouter>
)
const homeLink = getByTestId('homeNavBarButton')
expect(homeLink).toBeInTheDocument()
})
})

End-to-End Tests โ€” Using Cypress

  1. Make sure that the frontend and backend are running, with all dependencies installed.
  2. Open the Cypress test runner (in a new terminal): cd app โžก๏ธ npx cypress open

The following steps occur in the Cypress test runner:

  1. In the test runner, select "E2E Testing."
  2. You'll be prompted to choose a browser to run the tests in; any is fine.
  3. Cypress will open a new window containing a list of all the end-to-end tests.
  4. Click on a test file to run it.
  5. The selected test will begin execution. You'll see each step being performed in real-time within the Cypress GUI.
  6. If the test passes, the screen will turn green. If it fails, the screen will turn red, indicating which step failed.
  7. To run other test files, navigate back to the main page by selecting the "Specs" label in the sidebar.
  8. From the main page, you can select and run other test files one by one.

๐Ÿ‘‰ login_page

This test suite ensures that the login page can be accessed from the homepage, and checks for the presence of username and password input fields on the login page.

describe('Login Page', () => {
it('login page can be opened', () => {
cy.visit('http://localhost:5173')
cy.contains('Login')
cy.get('[data-testid=loginNavBarButton]').click()
cy.url().should('eq', 'http://localhost:5173/login')
cy.contains('Username').should('exist')
cy.contains('Password').should('exist')
})
})

๐Ÿ‘‰ messages_page

This test suite ensures that users can navigate to the messages page and post a message. It also verifies that the posted message is displayed on the page.

describe('Messages Page', () => {
it('Message page can be opened and a message can be posted', () => {
const message = 'Test message'
cy.visit('http://localhost:5173')
cy.get('[data-testid=loginNavBarButton]').click()
cy.get('[data-testid=loginButton]').click()
cy.url().should('eq', 'http://localhost:5173/messages')
cy.get('[data-testid="messageInput"]').type(message)
cy.get('[data-testid="submitMessageButton"]').click()
cy.contains('#postedMessage', message).should('be.visible')
})
})