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

Team Eka & Fegi #6

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
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
68 changes: 65 additions & 3 deletions _javascript/src/utils/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
import { expect, it, describe } from 'vitest'
import { double, formatCurrencyToIDR, calculatePriceWithDiscount } from './index'
import {
double,
formatCurrencyToIDR,
calculatePriceWithDiscount ,
getReadableFileSize,
toCamelCase,
capitalizeText,
isArrayEmpty,
getUrlQueryStringAsObject,
truncateString,
validateEmail,
} from './index'

describe('[utils]: double', () => {
it('should double a number', () => {
expect(double(2)).toBe(4)
})
})

describe('[utils: formatCurrencyToID]', () => {
describe('[utils]: formatCurrencyToID', () => {
it('should format a number to IDR', () => {
expect(formatCurrencyToIDR(1000)).toEqual('Rp 1.000')
})
Expand All @@ -17,7 +28,7 @@ describe('[utils: formatCurrencyToID]', () => {
})
})

describe('[utils: calculatePriceWithDiscount]', () => {
describe('[utils]: calculatePriceWithDiscount', () => {
it('should calculate the price with discount', () => {
expect(calculatePriceWithDiscount(1000, 50)).toBe(500)
})
Expand All @@ -30,3 +41,54 @@ describe('[utils: calculatePriceWithDiscount]', () => {
expect(() => calculatePriceWithDiscount(1000, 150)).toThrow('Discount percentage must be between 0 and 100')
})
})

describe('[utils]: getReadableFileSize', () => {
it('should convert bytes into units', () => {
expect(getReadableFileSize(1025, 0)).toBe('1 KB')
})
})

describe('[utils]: toCamelCase', () => {
it('should convert string to camelCase', () => {
expect(toCamelCase('front-end_bootcamp')).toBe('frontEndBootcamp')
})
})

describe('[utils]: capitalizeText', () => {
it('should convert string to capitalizeText', () => {
expect(capitalizeText('frontend bootcamp')).toBe('Frontend Bootcamp')
})
})

describe('[utils]: validateEmail', () => {
it('should check format email is valid', () => {
expect(validateEmail('[email protected]')).toBe('Valid email')
})
it('should check format email is not valid', () => {
expect(validateEmail('email@testcom')).toBe('Invalid email')
})
})

describe('[utils]: isArrayEmpty', () => {
it('should check isArrayEmpty false', () => {
expect(isArrayEmpty([])).toBe(true)
})
it('should check isArrayEmpty true', () => {
expect(isArrayEmpty([1])).toBe(false)
})
})

describe('[utils]: getUrlQueryStringAsObject', () => {
it('should convert url into object of params', () => {
expect(getUrlQueryStringAsObject('http://test.com?search=test&id=2')).toStrictEqual({
search: 'test',
id: '2'
})
})
})

describe('[utils]: truncateString', () => {
it('should truncate string with maxlegth', () => {
expect(truncateString('frontend bootcamp', 8)).toBe('frontend...')
})
})
2 changes: 2 additions & 0 deletions vue/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<div class="col-span-3" />
<ProductCard
v-for="product in filteredProducts"
data-cy="product-items"
:key="product.id"
:name="product.name"
:description="product.description"
Expand All @@ -23,6 +24,7 @@
/>
<div class="col-span-4 flex justify-center mt-8">
<button
data-cy="button-load"
v-show="!hasShownAllProducts"
type="button"
class="rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
Expand Down
10 changes: 5 additions & 5 deletions vue/components/ProductCard.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="group relative">
<div v-show="hasDiscount" class="absolute top-3 right-3 z-10">
<div v-show="hasDiscount" data-cy="product-discount" class="absolute top-3 right-3 z-10">
<span class="bg-red-500 rounded-md px-2.5 py-1.5 text-sm font-semibold text-white">
{{ discount }}%
</span>
Expand All @@ -19,14 +19,14 @@
<h3 class="text-md font-bold text-gray-700 pr-4 line-clamp-1">
<a href="#">
<span aria-hidden="true" class="absolute inset-0"></span>
{{ props.name }}
<span data-cy="product-name">{{ props.name }}</span>
</a>
</h3>
<p class="font-sm text-gray-500 line-clamp-1 pr-4">{{ props.description }}</p>
<p data-cy="product-desc" class="font-sm text-gray-500 line-clamp-1 pr-4">{{ props.description }}</p>
</div>
<div class="flex flex-col flex-shrink-0 justify-start">
<strike v-show="hasDiscount" class="text-gray-500 text-sm text-end">{{ formattedOriginalPrice }}</strike>
<p class="text-md font-bold text-gray-900">{{ formattedDiscountedPrice }}</p>
<strike data-cy="product-price__discount" v-show="hasDiscount" class="text-gray-500 text-sm text-end">{{ formattedOriginalPrice }}</strike>
<p data-cy="product-price" class="text-md font-bold text-gray-900">{{ formattedDiscountedPrice }}</p>
</div>
</div>
</div>
Expand Down
45 changes: 45 additions & 0 deletions vue/test/Page.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { describe, it, expect } from 'vitest';
import { mountSuspended } from '@nuxt/test-utils/runtime';
import App from '~/app.vue';
import { PRODUCTS } from '~/constants';

describe('Main App', () => {
it('should render 8 product in initial', async () => {
const wrapper = await mountSuspended(App);

const elements = wrapper.findAll('[data-cy="product-items"]');
expect(elements.length).toBe(8);
})

it('should input search matched with product', async () => {
const wrapper = await mountSuspended(App);

const query = 'Celana Kulot Hitam';
const input = wrapper.find('input');
await input.setValue(query);

const product = wrapper.findAll('[data-cy="product-name"]');
expect(product.length).toBe(1);
expect(product[0].text()).toBe(query);

const button = wrapper.find('[data-cy="button-load"]');
expect(button.element.style.display).toBe('none');

await input.setValue('');
const product2 = wrapper.findAll('[data-cy="product-name"]');
expect(product2.length).toBe(8);
})

it('should render all product when button load clicked', async () => {
const wrapper = await mountSuspended(App);

const button = wrapper.find('[data-cy="button-load"]');
await button.trigger('click');

const products = wrapper.findAll('[data-cy="product-name"]')
expect(products.length).toBe(PRODUCTS.length);

const button2 = wrapper.find('[data-cy="button-load"]');
expect(button2.element.style.display).toBe('none');
})
})
78 changes: 78 additions & 0 deletions vue/test/ProductCard.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { describe, it, expect } from 'vitest';
import { mountSuspended } from '@nuxt/test-utils/runtime';
import ProductCard from '@/components/ProductCard.vue';

const productDiscount = {
name: 'Kaos SALE',
description: 'kaos promo',
originalPrice: 130000,
discount: 50,
}
const productNotDiscount = {
name: 'Kaos Biasa',
description: 'tidak promo',
originalPrice: 150000,
discount: 0,
}

describe('[component]: ProductCard', () => {
it('should render image', async () => {
const wrapper = await mountSuspended(ProductCard, {
props: {...productDiscount}
})

const element = wrapper.find('img')
expect(element.exists()).toBe(true);
})

it('should render product name', async () => {
const wrapper = await mountSuspended(ProductCard, {
props: {...productDiscount}
})

const element = wrapper.find('[data-cy="product-name"]')
expect(element.text()).not.toBe('');
})

it('should render product description', async () => {
const wrapper = await mountSuspended(ProductCard, {
props: {...productDiscount}
})

const element = wrapper.find('[data-cy="product-desc"]')
expect(element.text()).not.toBe('');
})

it('should render product price', async () => {
const wrapper = await mountSuspended(ProductCard, {
props: {...productDiscount}
})

const element = wrapper.find('[data-cy="product-price"]')
expect(element.text()).not.toBe('');
})

it('should render discount label with striked price if has discount', async () => {
const wrapper = await mountSuspended(ProductCard, {
props: {...productDiscount}
})

const label = wrapper.find('[data-cy="product-discount"]')
expect(label.element.style.display).toBe('');

const price = wrapper.find('[data-cy="product-price__discount"]')
expect(price.element.style.display).toBe('');
})

it('should not render discount label with no stiked price if has no discount', async () => {
const wrapper = await mountSuspended(ProductCard, {
props: {...productNotDiscount}
})

const label = wrapper.find('[data-cy="product-discount"]')
expect(label.element.style.display).toBe('none');

const price = wrapper.find('[data-cy="product-price__discount"]')
expect(price.element.style.display).toBe('none');
})
})
3 changes: 3 additions & 0 deletions vue/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ import { defineVitestConfig } from '@nuxt/test-utils/config'

export default defineVitestConfig({
// any custom Vitest config you require
test: {
environment: 'nuxt'
}
})