Skip to content
Merged
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
8 changes: 8 additions & 0 deletions components/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,12 @@ module.exports = {
url: 'http://localhost/',
customExportConditions: ["node", "node-addons"],
},

globals: {
'vue-jest': {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('ui-'),
},
},
},
};
2 changes: 2 additions & 0 deletions components/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import status from './widgets/status/widget.vue';
import textfield from './widgets/textfield/widget.vue';
import table from './widgets/table/widget.vue';
import button from './widgets/button/widget.vue';
import complexTable from './widgets/complexTable/widget.vue';

import _store from './core/store';
import _bus from './core/eventBus';
Expand All @@ -30,6 +31,7 @@ export const Status = status;
export const Textfield = textfield;
export const Table = table;
export const Button = button;
export const ComplexTable = complexTable;

export const bus = _bus;
export const store = _store;
Expand Down
2 changes: 2 additions & 0 deletions components/src/widgets/button/widget.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ describe('Button widget', () => {
expect(result).toEqual(`
background-color: #2C98F0;
color: #FFF;
height: auto;
width: auto;
`);
});
});
Expand Down
10 changes: 10 additions & 0 deletions components/src/widgets/button/widget.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,21 @@ const emit = defineEmits(['clicked']);
type: String,
default: '#FFF',
},
height: {
type: String,
default: 'auto',
},
width: {
type: String,
default: 'auto',
},
});

const style = computed(() => `
background-color: ${props.backgroundColor};
color: ${props.color};
height: ${props.height};
width: ${props.width};
`);

const onClick = () => {
Expand Down
167 changes: 167 additions & 0 deletions components/src/widgets/complexTable/widget.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { mount } from '@vue/test-utils'
import ComplexTable from './widget';
import { nextTick } from 'vue'


describe('ComplexTable widget', () => {
let result;


describe('computed', () => {
describe('#totalPages', () => {
it('returns the total amount of pages', () => {
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 35,
items: ['hh'],
headers: ['jj'],
},
})

result = wrapper.vm.totalPages;

expect(result).toEqual(4);
});
});

describe('#previousButtonDisabled', () => {
it('returns true if the current page is 1', () => {
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 35,
items: ['hh'],
headers: ['jj'],
currentPage: 1,
},
})

result = wrapper.vm.previousButtonDisabled;

expect(result).toEqual(true);
});

it('returns false if the current page is not 1', () => {
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 35,
items: ['hh'],
headers: ['jj'],
currentPage: 2,
},
})

result = wrapper.vm.previousButtonDisabled;

expect(result).toEqual(false);
});
});

describe('#nextButtonDisabled', () => {
it('returns true if the current page is the last one', () => {
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 25,
items: ['hh'],
headers: ['jj'],
currentPage: 3,
},
})

result = wrapper.vm.nextButtonDisabled;

expect(result).toEqual(true);
});

it('returns false if the current page is not the last one', () => {
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 35,
items: ['hh'],
headers: ['jj'],
currentPage: 2,
},
})

result = wrapper.vm.nextButtonDisabled;

expect(result).toEqual(false);
});
});
});

describe('methods', () => {
describe('#previousClicked', () => {
it('emits previousClicked event', async () => {
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 35,
items: [],
headers: ['jj'],
currentPage: 2,
},
})

result = wrapper.vm.previousClicked();

expect(wrapper.emitted('previousClicked')).toBeTruthy()
});
});

describe('#nextClicked', () => {
it('emits nextClicked event', async () => {
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 35,
items: [],
headers: ['jj'],
currentPage: 2,
},
})

result = wrapper.vm.nextClicked();

expect(wrapper.emitted('nextClicked')).toBeTruthy()
});
});

describe('#prepareItems', () => {
it('returns the first 10 items', () => {
const itemsList = ['1','2','3','4','5','6','7','8','9','10','11','12'];
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 35,
items: itemsList,
headers: ['jj'],
currentPage: 2,
},
})

result = wrapper.vm.prepareItems(itemsList);

expect(result.length).toEqual(10);
});
});
});

describe('watch', () => {
describe('props.items', () => {
it('trigger the itemsLoaded event', async () => {
const wrapper = mount(ComplexTable, {
propsData: {
totalItems: 35,
items: [],
headers: ['jj'],
},
})

wrapper.setProps({
items: ['other']
});

await nextTick()

expect(wrapper.emitted('itemsLoaded'))
});
});
});
});
105 changes: 105 additions & 0 deletions components/src/widgets/complexTable/widget.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<template>
<ui-table :headers="props.headers">
<slot />
</ui-table>
<div class="buttons-container">
<ui-button
:disabled="previousButtonDisabled"
class="previous-button"
background-color="#fff"
color="#161616"
height="26px"
width="80px"
@clicked="previousClicked"
>
<div class="btn-text">
Previous
</div>
</ui-button>
<div>{{ currentPage }} / {{ totalPages }}</div>
<ui-button
:disabled="nextButtonDisabled"
class="next-button"
background-color="#fff"
color="#161616"
height="26px"
width="56px"
@clicked="nextClicked"
>
<div class="btn-text">
Next
</div>
</ui-button>
</div>
</template>

<script setup>
import { computed, watch } from 'vue';
import table from '~widgets/table/widget.vue';
import button from '~widgets/button/widget.vue';
import registerWidget from '~core/registerWidget';

registerWidget('ui-table', table);
registerWidget('ui-button', button);

const emit = defineEmits(['previousClicked', 'nextClicked', 'itemsLoaded']);
const ITEMS_PER_PAGE = 10;
const props = defineProps({
headers: {
type: Array,
required: true,
default: () => [],
},
items: {
type: Array,
required: true,
default: () => [],
},
currentPage: {
type: Number,
default: 1,
},
totalItems: {
type: Number,
default: 1,
}
});

const totalPages = computed(() => Math.ceil(props.totalItems / ITEMS_PER_PAGE))
const previousButtonDisabled = computed(() => props.currentPage === 1)
const nextButtonDisabled = computed(() => props.currentPage === totalPages.value)

const previousClicked = () => emit('previousClicked');

const nextClicked = () => emit('nextClicked');

const prepareItems = (items) => {
return items.slice(0, ITEMS_PER_PAGE)
}

watch(() => props.items, function(newItems) {
emit('itemsLoaded', prepareItems(newItems));
}, { deep: true, immediate: true });
</script>

<style lang="stylus" scoped>
.buttons-container {
display: flex;
align-items: center;
height: 48px;

.previous-button {
margin-right: 16px;
border: 1px solid #e0e0e0;
}

.next-button {
margin-left: 16px;
border: 1px solid #e0e0e0;
}

.btn-text {
text-transform: capitalize;
}
}
</style>