Coder Social home page Coder Social logo

notes-full-stack's Introduction

Notes Full Stack

Link to the App

Notes Full Stack

Set the environment variables on Fly.io

fly secrets set MONGODB_URI='...'

Tests

npm test -- tests/note_api.test.js
npm test -- -t "a specific note is within the returned notes"
npm test -- -t 'notes'

Frontend tests

npm install --save-dev @testing-library/react @testing-library/jest-dom
npm install --save-dev @testing-library/user-event

npm test
CI=true npm test
CI=true npm test -- --coverage
import React from 'react'
import '@testing-library/jest-dom/extend-expect'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import Note from './Note'
import Togglable from './Togglable'
import NoteForm from './NoteForm'

test('Test description...', async () => {
  const note = {
    content: 'Component testing is done with react-testing-library',
    important: true,
  }

  // 1.
  render(<Note note={note} />)

  // screen.debug()
  // screen.debug(element)

  const element = screen.getByText(
    'Component testing is done with react-testing-library'
  )
  expect(element).toBeDefined()

  // 2.
  const { container } = render(<Note note={note} />)
  const div = container.querySelector('.note')
  expect(div).toHaveTextContent(
    'Component testing is done with react-testing-library'
  )

  // 3.
  const element = screen.getByTestId('custom-element')
  expect(element).toBeDefined()

  // 4.
  const mockHandler = jest.fn()
  render(<Note note={note} toggleImportance={mockHandler} />)
  const user = userEvent.setup()
  const button = screen.getByText('make not important')
  await user.click(button)
  expect(mockHandler.mock.calls).toHaveLength(1)

  // 5.
  describe('<Togglable />', () => {
    let container

    beforeEach(() => {
      container = render(
        <Togglable buttonLabel='show...'>
          <div className='testDiv'>togglable content</div>
        </Togglable>
      ).container
    })

    test('renders its children', async () => {
      await screen.findAllByText('togglable content')
    })

    test('at start the children are not displayed', () => {
      const div = container.querySelector('.togglableContent')
      expect(div).toHaveStyle('display: none')
    })

    test('after clicking the button, children are displayed', async () => {
      const user = userEvent.setup()
      const button = screen.getByText('show...')
      await user.click(button)

      const div = container.querySelector('.togglableContent')
      expect(div).not.toHaveStyle('display: none')
    })

    test('toggled content can be closed', async () => {
      const user = userEvent.setup()
      const button = screen.getByText('show...')
      await user.click(button)

      const closeButton = screen.getByText('cancel')
      await user.click(closeButton)

      const div = container.querySelector('.togglableContent')
      expect(div).toHaveStyle('display: none')
    })
  })

  // 6.
  test('<NoteForm /> updates parent state and calls onSubmit', async () => {
    const createNote = jest.fn()
    const user = userEvent.setup()

    render(<NoteForm createNote={createNote} />)

    const input = screen.getByRole('textbox')
    const sendButton = screen.getByText('save')

    await user.type(input, 'testing a form...')
    await user.click(sendButton)

    expect(createNote.mock.calls).toHaveLength(1)
    expect(createNote.mock.calls[0][0].content).toBe('testing a form...')
  })

  // const inputs = screen.getAllByRole('textbox')
  // await user.type(inputs[0], 'testing a form...')

  test('<NoteForm /> updates parent state and calls onSubmit', () => {
    const createNote = jest.fn()

    render(<NoteForm createNote={createNote} />)

    const input = screen.getByPlaceholderText('write note content here')
    const sendButton = screen.getByText('save')

    userEvent.type(input, 'testing a form...')
    userEvent.click(sendButton)

    expect(createNote.mock.calls).toHaveLength(1)
    expect(createNote.mock.calls[0][0].content).toBe('testing a form...')
  })

  // const { container } = render(<NoteForm createNote={createNote} />)
  // const input = container.querySelector('#note-input')

  // const element = screen.getByText('Does not work anymore :(', { exact: false })

  // const element = await screen.findByText('Does not work anymore :(')

  test('does not render this', () => {
    const note = {
      content: 'This is a reminder',
      important: true,
    }

    render(<Note note={note} />)

    const element = screen.queryByText('do not want this thing to be rendered')
    expect(element).toBeNull()
  })
})

Authentication

The other solution is to save info about each token to backend database and to check for each API request if the access right corresponding to the token is still valid. With this scheme, access rights can be revoked at any time. This kind of solution is often called a server-side session.

The negative aspect of server-side sessions is the increased complexity in the backend and also the effect on performance since the token validity needs to be checked for each API request to the database. A database access is considerably slower compared to checking the validity of the token itself. That is why it is quite common to save the session corresponding to a token to a key-value database such as Redis that is limited in functionality compared to eg. MongoDB or relational database but extremely fast in some usage scenarios.

When server-side sessions are used, the token is quite often just a random string, that does not include any information about the user as it is quite often the case when jwt-tokens are used. For each API request, the server fetches the relevant information about the identity of the user from the database. It is also quite usual that instead of using Authorization-header, cookies are used as the mechanism for transferring the token between the client and the server.

notes-full-stack's People

Contributors

salva1973 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.