Storybook
GitLab v19.1gitlab-org/gitlab 프로젝트의 Storybook은 GitLab Pages 사이트에서 확인할 수 있습니다. Storybook 의존성과 설정은 storybook/ 디렉터리 하위에 위치합니다. gitlab 프로젝트의 루트 디렉터리에서 Storybook을 빌드하고 실행하려면 다음 단계를 따르세요:
gitlab-org/gitlab 프로젝트의 Storybook은 GitLab Pages 사이트에서 확인할 수 있습니다.
로컬 개발 환경에서의 Storybook#
Storybook 의존성과 설정은 storybook/ 디렉터리 하위에 위치합니다.
gitlab 프로젝트의 루트 디렉터리에서 Storybook을 빌드하고 실행하려면 다음 단계를 따르세요:
-
Storybook 의존성 설치:
yarn storybook:install -
Storybook 사이트 빌드:
yarn storybook:start -
Storybook 항목 테스트:
yarn storybook:dev:test
자동화된 접근성 테스트에 대한 자세한 내용은 접근성 Storybook 테스트를 참고하세요.
Storybook에 컴포넌트 추가하기#
gitlab 리포지터리 내의 모든 Vue 컴포넌트에 스토리를 추가할 수 있습니다.
스토리를 추가하려면 다음 단계를 따르세요:
-
Vue 컴포넌트와 동일한 디렉터리에 새
.stories.js파일을 생성하세요. 파일명은 Vue 컴포넌트와 동일한 접두어를 사용해야 합니다.vue_shared/ ├─ components/ │ ├─ sidebar │ | ├─ todo_toggle │ | | ├─ todo_button.vue │ │ | ├─ todo_button.stories.js -
스토리는 컴포넌트에 노출된 props 및 이벤트와 관련하여 눈에 띄게 다른 UI 상태를 각각 시연해야 합니다.
스토리 작성 방법은 공식 Storybook 가이드를 참고하세요.
스토리의 title 필드는 javascripts/ 디렉터리 기준의 컴포넌트 파일 경로에서 /components 부분을 제외하여 지정하세요.
예를 들어 컴포넌트 위치가 app/assets/javascripts/vue_shared/components/sidebar/todo_toggle/todo_button.vue인 경우,
스토리 title은 vue_shared/sidebar/todo_toggle/todo_button으로 지정하세요.
컴포넌트가 ee/ 디렉터리에 있는 경우, 스토리 title에도 ee/ 접두어를 붙여야 합니다.
이렇게 하면 Storybook 네비게이션이 내부 디렉터리 구조와 최대한 일치하게 됩니다.
GraphQL 쿼리 및 뮤테이션 목킹#
Apollo Client를 사용하는 컴포넌트의 스토리를 작성하려면, helpers/mock_apollo_helper에서 createMockApollo를 사용하세요.
[query, handlerFn] 튜플 배열을 전달하며, 각 핸들러는 쿼리 변수를 받아 예상 응답 형태로 resolve되는 Promise를 반환해야 합니다.
import createMockApollo from 'helpers/mock_apollo_helper';
import myQuery from './graphql/my_query.query.graphql';
import MyComponent from './my_component.vue';
const MOCK_DATA = [{ id: '1', name: 'Example' }];
export default {
component: MyComponent,
title: 'path/to/my_component',
};
const Template = (args, { argTypes }) => ({
components: { MyComponent },
apolloProvider: createMockApollo([
[
myQuery,
() =>
Promise.resolve({
data: {
currentUser: {
id: 'gid://gitlab/User/1',
items: { nodes: MOCK_DATA },
},
},
}),
],
]),
props: Object.keys(argTypes),
template: '<my-component v-bind="$props" />',
});
export const Default = Template.bind({});
Default.args = {};
각 스토리 변형은 로딩, 빈 상태, 오류 등 서로 다른 상태를 시뮬레이션하기 위해 다른 핸들러를 전달할 수 있습니다:
export const Empty = (args, { argTypes }) => ({
components: { MyComponent },
apolloProvider: createMockApollo([
[myQuery, () => Promise.resolve({ data: { currentUser: { id: '1', items: { nodes: [] } } } })],
]),
props: Object.keys(argTypes),
template: '<my-component v-bind="$props" />',
});
export const LoadingState = (args, { argTypes }) => ({
components: { MyComponent },
apolloProvider: createMockApollo([[myQuery, () => new Promise(() => {})]]),
props: Object.keys(argTypes),
template: '<my-component v-bind="$props" />',
});
Vuex 스토어 사용하기#
Vuex 스토어에 접근이 필요한 컴포넌트의 스토리를 작성하려면, Story 컨텍스트에서 제공하는 createVuexStore 메서드를 사용하세요.
import { withVuexStore } from 'storybook_addons/vuex_store';
import DurationChart from './duration-chart.vue';
const Template = (_, { argTypes, createVuexStore }) => {
return {
components: { DurationChart },
store: createVuexStore({
state: {},
getters: {},
modules: {},
}),
props: Object.keys(argTypes),
template: '<duration-chart />',
};
};
export default {
component: DurationChart,
title: 'ee/analytics/cycle_analytics/components/duration_chart',
decorators: [withVuexStore],
};
export const Default = Template.bind({});
Default.args = {};