feat: nová stránka pro návrhy na vylepšení
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 21s
CI / Build server (push) Successful in 24s
CI / Build client (push) Successful in 38s
CI / Playwright E2E tests (push) Successful in 1m18s
CI / Build and push Docker image (push) Successful in 40s
CI / Notify (push) Successful in 2s
CI / Generate TypeScript types (push) Successful in 10s
CI / Server unit tests (push) Successful in 21s
CI / Build server (push) Successful in 24s
CI / Build client (push) Successful in 38s
CI / Playwright E2E tests (push) Successful in 1m18s
CI / Build and push Docker image (push) Successful in 40s
CI / Notify (push) Successful in 2s
This commit is contained in:
27 files changed
+857
-515
No files matched your search
@@ -0,0 +1,126 @@
|
||||
import { resetMemoryStorage } from '../storage/memory';
|
||||
import { addSuggestion, deleteSuggestion, listSuggestions, voteSuggestion } from '../suggestions';
|
||||
|
||||
const AUTHOR = 'tomas';
|
||||
const VOTER = 'petr';
|
||||
const OTHER = 'jana';
|
||||
|
||||
beforeEach(() => {
|
||||
resetMemoryStorage();
|
||||
});
|
||||
|
||||
/** Pomocná funkce: vytvoří návrh a vrátí jeho id (z pohledu autora). */
|
||||
async function createSuggestion(author = AUTHOR, title = 'Tmavý režim', description = 'Přidat tmavý režim aplikace') {
|
||||
const list = await addSuggestion(author, title, description);
|
||||
return list.find(s => s.title === title)!.id;
|
||||
}
|
||||
|
||||
describe('addSuggestion', () => {
|
||||
test('přidá návrh a autorovi nastaví hlas pro', async () => {
|
||||
const list = await addSuggestion(AUTHOR, 'Tmavý režim', 'Popis');
|
||||
expect(list).toHaveLength(1);
|
||||
const s = list[0];
|
||||
expect(s.author).toBe(AUTHOR);
|
||||
expect(s.title).toBe('Tmavý režim');
|
||||
expect(s.description).toBe('Popis');
|
||||
expect(s.voteScore).toBe(1);
|
||||
expect(s.myVote).toBe('up');
|
||||
expect(s.isMine).toBe(true);
|
||||
});
|
||||
|
||||
test('ořízne mezery a odmítne prázdný název i popis', async () => {
|
||||
await expect(addSuggestion(AUTHOR, ' ', 'popis')).rejects.toThrow();
|
||||
await expect(addSuggestion(AUTHOR, 'název', ' ')).rejects.toThrow();
|
||||
const list = await addSuggestion(AUTHOR, ' Název ', ' Popis ');
|
||||
expect(list[0].title).toBe('Název');
|
||||
expect(list[0].description).toBe('Popis');
|
||||
});
|
||||
|
||||
test('jeden uživatel může přidat více návrhů', async () => {
|
||||
await addSuggestion(AUTHOR, 'První', 'popis');
|
||||
const list = await addSuggestion(AUTHOR, 'Druhý', 'popis');
|
||||
expect(list).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('listSuggestions', () => {
|
||||
test('řadí sestupně dle skóre', async () => {
|
||||
const lowId = await createSuggestion(AUTHOR, 'Nízké', 'popis');
|
||||
const highId = await createSuggestion(OTHER, 'Vysoké', 'popis');
|
||||
// "Vysoké" dostane další hlas pro
|
||||
await voteSuggestion(VOTER, highId, 'up');
|
||||
|
||||
const list = await listSuggestions(VOTER);
|
||||
expect(list[0].id).toBe(highId);
|
||||
expect(list[0].voteScore).toBe(2);
|
||||
expect(list[1].id).toBe(lowId);
|
||||
});
|
||||
|
||||
test('myVote a isMine jsou relativní k uživateli', async () => {
|
||||
const id = await createSuggestion(AUTHOR);
|
||||
const asAuthor = (await listSuggestions(AUTHOR))[0];
|
||||
expect(asAuthor.isMine).toBe(true);
|
||||
expect(asAuthor.myVote).toBe('up');
|
||||
|
||||
const asOther = (await listSuggestions(VOTER))[0];
|
||||
expect(asOther.isMine).toBe(false);
|
||||
expect(asOther.myVote).toBeUndefined();
|
||||
// Seznamy hlasujících se klientovi neposílají
|
||||
expect((asOther as any).upvoters).toBeUndefined();
|
||||
expect(id).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('voteSuggestion', () => {
|
||||
test('hlas pro a proti od jiného uživatele', async () => {
|
||||
const id = await createSuggestion();
|
||||
let list = await voteSuggestion(VOTER, id, 'up');
|
||||
expect(list[0].voteScore).toBe(2);
|
||||
expect(list.find(s => s.id === id)!.voteScore).toBe(2);
|
||||
|
||||
// přehlasování z pro na proti
|
||||
list = await voteSuggestion(VOTER, id, 'down');
|
||||
// autor +1, voter -1 => 0
|
||||
expect(list[0].voteScore).toBe(0);
|
||||
expect((await listSuggestions(VOTER))[0].myVote).toBe('down');
|
||||
});
|
||||
|
||||
test('klik na aktivní směr hlas zruší', async () => {
|
||||
const id = await createSuggestion();
|
||||
await voteSuggestion(VOTER, id, 'up');
|
||||
const list = await voteSuggestion(VOTER, id, 'up');
|
||||
// zůstává jen autorův hlas
|
||||
expect(list[0].voteScore).toBe(1);
|
||||
expect((await listSuggestions(VOTER))[0].myVote).toBeUndefined();
|
||||
});
|
||||
|
||||
test('autor může svůj automatický hlas odebrat', async () => {
|
||||
const id = await createSuggestion();
|
||||
const list = await voteSuggestion(AUTHOR, id, 'up');
|
||||
expect(list[0].voteScore).toBe(0);
|
||||
expect((await listSuggestions(AUTHOR))[0].myVote).toBeUndefined();
|
||||
});
|
||||
|
||||
test('hlasování pro neexistující návrh vyhodí chybu', async () => {
|
||||
await expect(voteSuggestion(VOTER, 'neexistuje', 'up')).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteSuggestion', () => {
|
||||
test('autor smaže svůj návrh včetně hlasů', async () => {
|
||||
const id = await createSuggestion();
|
||||
await voteSuggestion(VOTER, id, 'up');
|
||||
const list = await deleteSuggestion(AUTHOR, id);
|
||||
expect(list).toHaveLength(0);
|
||||
});
|
||||
|
||||
test('cizí uživatel nemůže smazat návrh', async () => {
|
||||
const id = await createSuggestion();
|
||||
await expect(deleteSuggestion(VOTER, id)).rejects.toThrow();
|
||||
expect(await listSuggestions(AUTHOR)).toHaveLength(1);
|
||||
});
|
||||
|
||||
test('smazání neexistujícího návrhu vyhodí chybu', async () => {
|
||||
await expect(deleteSuggestion(AUTHOR, 'neexistuje')).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user