Komiser dashboard is a Next.js project bootstrapped with create-next-app
.
Full frontend stack:
- 🖥
Next.js
- 📜
Typescript
- 🎨
Tailwind
- 📖
Storybook
- 🧪
Jest
- 📚
React Testing Library
Follow the Contribution Guide first if you haven't done so already. Then come back here and follow the next steps:
From the Komiser root folder start the Komiser server by running:
go run *.go start --config /path/to/config.toml
In a different terminal tab navigate to the /dashboard
folder:
cd dashboard
and run:
npm install
NEXT_PUBLIC_API_URL=http://localhost:3000 npm run dev
Alternatively, you can create an .env file with it, either manually or by running:
echo "NEXT_PUBLIC_API_URL=http://localhost:3000" > .env
and simply run:
npm run dev
2. Open http://localhost:3002/. If you see the dashboard, 🎉 congrats! It's all up and running correctly.
❗ If you get an error page such as this, please refer to the logs and our docs.
Komiser components are documented under /components
💡 Hint: We have the following import aliases defined in
tsconfig.json
{ "@components/": "/dashboard/components/", "@services/": "/dashboard/services/", "@environments/": "/dashboard/environments/", "@utils/": "/dashboard/utils/", "@styles/": "/dashboard/styles/" }
You can find all the shared Components also inside Storybook. If you're implementing a new Story, please check for existing or new components with Storybook. We will require a story for new shared components like icons, inputs or similar.
Component convention:
-
📁 Component folder: component name in
kebab-case
-
📄 Component file: component name in
UpperCamelCase.*
-
📖 Component story: component name in
UpperCamelCase.stories.*
-
🎭 Component story mock (if needed): component name in
UpperCamelCase.mocks.*
-
🧪 Component unit test: component name in
UpperCamelCase.test.*
-
🧐 Check
Card
example for more details:
Additional instructions:
-
📖 To view this component on Storybook, run:
npm run storybook
, then pickCard
-
🧪 To run the unit tests, run:
npm run test:watch
, hitp
, thencard
We use Jest & React Testing Library for our unit tests.
- To run the unit tests, run:
npm run test
Testing convention:
- ✅ All new Utils need to be tested. Existing ones when being changed
- ✅ All tests should be wrapped in a
describe
- ✅ If it's a unit test for a function:
describe('[replace with function name]', () => { ... })
- ✅ If it's a unit test for a util:
describe('[replace with util name] util', () => { ... })
- ✅ If it's a unit test for a component:
describe('[replace with component name]', () => { ... })
- ✅ A test should use 'it' for the test function:
it('should do something', () => { ... })
Testing examples:
- Simple Jest unit test example (snippet from
/utils/formatNumber.test.ts
):
import formatNumber from './formatNumber';
describe('formatNumber util', () => {
it('should format number (over a thousand) in short notation', () => {
const result = formatNumber(12345);
expect(result).toBe('12K');
});
...
});
- Jest & Testing library example (snippet from
/components/card/Card.test.tsx
):
import { render, screen } from '@testing-library/react';
import RefreshIcon from '../icons/RefreshIcon';
import Card from './Card';
describe('Card', () => {
it('should render card component without crashing', () => {
render(
<Card
label="Test card"
value={500}
icon={<RefreshIcon width={24} height={24} />}
/>
);
});
it('should display the value formatted', () => {
render(
<Card
label="Test card"
value={5000}
icon={<RefreshIcon width={24} height={24} />}
/>
);
const formattedNumber = screen.getByTestId('formattedNumber');
expect(formattedNumber).toHaveTextContent('5K');
});
...
});
If you're looking for an example with event firing and state updates, have a look at components/select-checkbox/SelectCheckbox.test.tsx
:
it('opens the dropdown when clicked', () => {
const { getByRole, getByText } = render(
<SelectCheckbox
label="Test Label"
query="provider"
exclude={[]}
setExclude={() => {}}
/>
);
fireEvent.click(getByRole('button'));
expect(getByText('Item 1')).toBeInTheDocument();
expect(getByText('Item 2')).toBeInTheDocument();
expect(getByText('Item 3')).toBeInTheDocument();
});
Storybook is a tool for UI development. It makes development faster by isolating components. This allows you to work on one component at a time. If you create a new shared component or want to visualize variations of an existing one, follow these steps:
-
To view this component on Storybook locally, run:
npm run storybook
, then pick an example (Card
) or your new component story
In the same directory as your component, create a Storybook story:
- Create a story file: component name in
UpperCamelCase.stories.*
.
Here's a basic story format:
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import YourComponent from './YourComponent';
export default {
title: 'Path/To/YourComponent',
component: YourComponent
} as ComponentMeta<typeof YourComponent>;
const Template: ComponentStory<typeof YourComponent> = args => (
<YourComponent {...args} />
);
export const Default = Template.bind({});
Default.args = {
// default props here...
};
You can create multiple variations of your component by replicating the Default
pattern. For example, if your component has a variation for a "disabled" state:
export const Disabled = Template.bind({});
Disabled.args = {
// props to set the component to its disabled state...
};
If your component requires mock data, create a mock file: component name in UpperCamelCase.mocks.*
. Import this data into your story file to use with your component variations.
Run Storybook:
npm run storybook
Your component should now appear in the Storybook UI. Navigate to it, and verify all the variations display correctly.
Add a brief description and any notes on your component's functionality within the Storybook UI. Use the parameters
object in your default export:
export default {
title: 'Path/To/YourComponent',
component: YourComponent,
parameters: {
docs: {
description: {
component: 'Your description here...'
}
}
}
} as ComponentMeta<typeof YourComponent>;
Remember: Storybook is not just a tool but also a way to document components. Ensure you provide meaningful names, descriptions, and use cases to help other developers understand the use and purpose of each component.
We welcome all contributors to join us on the mission of improving Komiser, especially when it comes to writing tests and adding documentation.
Not sure where to start?
- 📖 Read the contributor guidelines
- 💬 Join our Discord and hang with us on #contributors channel.
To learn more about our stack, take a look at the following resources:
- Next.js documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
- Tailwind documentation
- Storybook documentation
- Jest documentation
- React testing library documentation