Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dark mode #6

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ Otherwise, it is mandatory.
a. Add at least 3 automated browser tests using puppeteer, testing key features of your choice.
b. Add component tests (using `jest`) to your work from *part 1*.

### Part 5 - Dark Mode
Agents use this system all day, white can be quite a tiring color on the eyes 😫.

1.Add a "dark mode" button or clickable text that will change the background of the UI to `black` and the basic font of the outline to `white`.
2.When the "dark mode" is enabled let the user revert it with a button or clickable text that will change the background of the UI to `white` and the basic font of the outline to `black`.
use "dark mode" and "light mode" as the text for those different button states.

## General notes
- Test your work well. Think of edge cases. Think of how users will use it, and make sure your work is of high quality
Expand Down
18 changes: 18 additions & 0 deletions client/src/App.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.darkMode {
color: white;
background-color: black;
}

body {
font-family: 'Open Sans', sans-serif;

Expand All @@ -20,6 +25,19 @@ body {
font-size: 12px;
margin: 12px 5px;
}
.darkModeCheckBox {
line-height: 20px;
text-align: right;
input {
vertical-align: bottom;
margin-right: 8px;
box-shadow: 0 2px 6px 1px #e1e5e8;
cursor: pointer;
}
label {
cursor: pointer;
}
}

header {
width: 100%;
Expand Down
126 changes: 71 additions & 55 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,83 @@
import React from 'react';
import './App.scss';
import {createApiClient, Ticket} from './api';
import { createApiClient, Ticket } from './api';

export type AppState = {
tickets?: Ticket[],
search: string;
tickets?: Ticket[],
search: string;
darkMode: boolean;
}

const api = createApiClient();

export class App extends React.PureComponent<{}, AppState> {

state: AppState = {
search: ''
}

searchDebounce: any = null;

async componentDidMount() {
this.setState({
tickets: await api.getTickets()
});
}

renderTickets = (tickets: Ticket[]) => {

const filteredTickets = tickets
.filter((t) => (t.title.toLowerCase() + t.content.toLowerCase()).includes(this.state.search.toLowerCase()));


return (<ul className='tickets'>
{filteredTickets.map((ticket) => (<li key={ticket.id} className='ticket'>
<h5 className='title'>{ticket.title}</h5>
<footer>
<div className='meta-data'>By {ticket.userEmail} | { new Date(ticket.creationTime).toLocaleString()}</div>
</footer>
</li>))}
</ul>);
}

onSearch = async (val: string, newPage?: number) => {

clearTimeout(this.searchDebounce);

this.searchDebounce = setTimeout(async () => {
this.setState({
search: val
});
}, 300);
}

render() {
const {tickets} = this.state;

return (<main>
<h1>Tickets List</h1>
<header>
<input type="search" placeholder="Search..." onChange={(e) => this.onSearch(e.target.value)}/>
</header>
{tickets ? <div className='results'>Showing {tickets.length} results</div> : null }
{tickets ? this.renderTickets(tickets) : <h2>Loading..</h2>}
</main>)
}
state: AppState = {
search: '',
darkMode: false
}

searchDebounce: any = null;

async componentDidMount() {
this.setState({
tickets: await api.getTickets()
});
}

renderDarkModeCheckbox = () => {
return (<div>

<button onClick={() => {
this.setState({
darkMode: !this.state.darkMode
})
}}>
{this.state.darkMode ? 'Light Mode' : 'Dark Mode'}
</button>
</div>);
}

renderTickets = (tickets: Ticket[]) => {

const filteredTickets = tickets
.filter((t) => (t.title.toLowerCase() + t.content.toLowerCase()).includes(this.state.search.toLowerCase()));


return (<ul className='tickets'>
{filteredTickets.map((ticket) => (<li key={ticket.id} className='ticket'>
<h5 className='title'>{ticket.title}</h5>
<footer>
<div className='meta-data'>By {ticket.userEmail} | {new Date(ticket.creationTime).toLocaleString()}</div>
</footer>
</li>))}
</ul>);
}

onSearch = async (val: string, newPage?: number) => {

clearTimeout(this.searchDebounce);

this.searchDebounce = setTimeout(async () => {
this.setState({
search: val
});
}, 300);
}

render() {
const { tickets, darkMode } = this.state;
document.body.className = darkMode ? 'darkMode' : '';
return (<main>
{this.renderDarkModeCheckbox()}
<h1>Tickets List</h1>
<header>
<input type="search" placeholder="Search..." onChange={(e) => this.onSearch(e.target.value)}/>
</header>
{tickets ? <div className='results'>Showing {tickets.length} results</div> : null}
{tickets ? this.renderTickets(tickets) : <h2>Loading..</h2>}
</main>)
}
}

export default App;
export default App;
Binary file added images/Dark mode.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

77 changes: 77 additions & 0 deletions tester/darkmode.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { getElementsByText } from "./getElementsByText";

const puppeteer = require('puppeteer');
const serverData = require('../server/data.json');
import { staticsUrl } from '@fed-exam/config';

let browser;
let page;

beforeAll(async () => {
browser = await puppeteer.launch();
page = await browser.newPage();
await page.setViewport({
width: 1280,
height: 1080,
deviceScaleFactor: 1,
});
})

afterAll(async () => {
await browser.close();
})

const goToMainPage = async () => {
await page.goto(staticsUrl);
//await page.screenshot({ path: 'main_page.png' });
}

describe("Dark Mode", () => {

test('dark button exist ', async () => {
await goToMainPage();

const darkButtons = await getElementsByText(['dark mode', 'Dark mode', 'Dark Mode', 'darkmode', 'darkMode'], page)
expect(darkButtons.length).toBe(1)
});

test('light button doesnt exist by default', async () => {
await goToMainPage();

const lightButtons = await getElementsByText(['light mode', 'Light mode', 'Light Mode', 'lightmode', 'lightMode'], page)
expect(lightButtons.length).toBe(0)
});

test('light button exist after clicking the dark button', async () => {
await goToMainPage();

const darkButtons = await getElementsByText(['dark mode', 'Dark mode', 'Dark Mode', 'darkmode', 'darkMode'], page)
await darkButtons[0].click();

const lightButtons = await getElementsByText(['light mode', 'Light mode', 'Light Mode', 'lightmode', 'lightMode'], page)
expect(lightButtons.length).toBe(1)
});

test('Background is white and text is grayish without change', async () => {
await goToMainPage();
const docBody = await page.$('body')
const title = await page.$('.title')
let pageBackGroundColor = await page.evaluate(el => getComputedStyle(el).backgroundColor, docBody)
let titleColor = await page.evaluate(el => getComputedStyle(el).color, title)
expect(pageBackGroundColor).toBe('rgb(245, 249, 252)')
expect(titleColor).toBe('rgb(32, 69, 94)')
});

test('Background is black and color is white after click', async () => {
await goToMainPage();
const darkButtons = await getElementsByText(['dark mode', 'Dark mode', 'Dark Mode', 'darkmode', 'darkMode'], page)
await darkButtons[0].click();
const docBody = await page.$('body')
const title = await page.$('.title')
let pageBackGroundColor = await page.evaluate(el => getComputedStyle(el).backgroundColor, docBody)
let titleColor = await page.evaluate(el => getComputedStyle(el).color, title)
expect(pageBackGroundColor).toBe('rgb(0, 0, 0)')
expect(titleColor).toBe('rgb(32, 69, 94)')
});
});

54 changes: 0 additions & 54 deletions tester/e2e.test.ts

This file was deleted.