Commit 3d256a06 authored by Miguel Rincon's avatar Miguel Rincon

Merge branch '344104-project-feature-gl-toggle' into 'master'

Add helpers to init GlToggle instances

See merge request gitlab-org/gitlab!80293
parents f104252a 871518a8
import { kebabCase } from 'lodash';
import Vue from 'vue';
import { GlToggle } from '@gitlab/ui';
import { parseBoolean } from '~/lib/utils/common_utils';
export const initToggle = (el) => {
if (!el) {
return false;
}
const {
name,
isChecked,
disabled,
isLoading,
label,
help,
labelPosition,
...dataset
} = el.dataset;
return new Vue({
el,
props: {
disabled: {
type: Boolean,
required: false,
default: parseBoolean(disabled),
},
isLoading: {
type: Boolean,
required: false,
default: parseBoolean(isLoading),
},
},
data() {
return {
value: parseBoolean(isChecked),
};
},
render(h) {
return h(GlToggle, {
props: {
name,
value: this.value,
disabled: this.disabled,
isLoading: this.isLoading,
label,
help,
labelPosition,
},
class: el.className,
attrs: Object.fromEntries(
Object.entries(dataset).map(([key, value]) => [`data-${kebabCase(key)}`, value]),
),
on: {
change: (newValue) => {
this.value = newValue;
this.$emit('change', newValue);
},
},
});
},
});
};
-# This partial renders a GlToggle root element.
-# To actually initialize the component, make sure to call the initToggle helper from ~/toggles.
- classes = local_assigns.fetch(:classes)
- name = local_assigns.fetch(:name, nil)
- is_checked = local_assigns.fetch(:is_checked, false).to_s
- disabled = local_assigns.fetch(:disabled, false).to_s
- is_loading = local_assigns.fetch(:is_loading, false).to_s
- label = local_assigns.fetch(:label, nil)
- help = local_assigns.fetch(:help, nil)
- label_position = local_assigns.fetch(:label_position, nil)
- data = local_assigns.fetch(:data, {})
%span{ class: classes,
data: { name: name,
is_checked: is_checked,
disabled: disabled,
is_loading: is_loading,
label: label,
help: help,
label_position: label_position,
**data } }
-# Leverage this block to render a rich help text. To render a plain text help text,
-# prefer the `help` parameter.
- if yield.present?
.gl-text-secondary.gl-mt-1
= yield
import { createWrapper } from '@vue/test-utils';
import { GlToggle } from '@gitlab/ui';
import { initToggle } from '~/toggles';
// Selectors
const TOGGLE_WRAPPER_CLASS = '.gl-toggle-wrapper';
const TOGGLE_LABEL_CLASS = '.gl-toggle-label';
const CHECKED_CLASS = '.is-checked';
const DISABLED_CLASS = '.is-disabled';
const LOADING_CLASS = '.toggle-loading';
const HELP_TEXT_SELECTOR = '[data-testid="toggle-help"]';
// Toggle settings
const toggleClassName = 'js-custom-toggle-class';
const toggleLabel = 'Toggle label';
describe('toggles/index.js', () => {
let instance;
let toggleWrapper;
const createRootEl = (dataAttrs) => {
const dataset = {
label: toggleLabel,
...dataAttrs,
};
const el = document.createElement('span');
el.classList.add(toggleClassName);
Object.entries(dataset).forEach(([key, value]) => {
el.dataset[key] = value;
});
document.body.appendChild(el);
return el;
};
const initToggleWithOptions = (options = {}) => {
const el = createRootEl(options);
instance = initToggle(el);
toggleWrapper = document.querySelector(TOGGLE_WRAPPER_CLASS);
};
afterEach(() => {
document.body.innerHTML = '';
instance = null;
toggleWrapper = null;
});
describe('initToggle', () => {
describe('default state', () => {
beforeEach(() => {
initToggleWithOptions();
});
it('attaches a GlToggle to the element', async () => {
expect(toggleWrapper).not.toBe(null);
expect(toggleWrapper.querySelector(TOGGLE_LABEL_CLASS).textContent).toBe(toggleLabel);
});
it('passes CSS classes down to GlToggle', () => {
expect(toggleWrapper.className).toContain(toggleClassName);
});
it('is not checked', () => {
expect(toggleWrapper.querySelector(CHECKED_CLASS)).toBe(null);
});
it('is enabled', () => {
expect(toggleWrapper.querySelector(DISABLED_CLASS)).toBe(null);
});
it('is not loading', () => {
expect(toggleWrapper.querySelector(LOADING_CLASS)).toBe(null);
});
it('emits "change" event when value changes', () => {
const wrapper = createWrapper(instance);
const event = 'change';
const listener = jest.fn();
instance.$on(event, listener);
expect(listener).toHaveBeenCalledTimes(0);
wrapper.find(GlToggle).vm.$emit(event, true);
expect(listener).toHaveBeenCalledTimes(1);
expect(listener).toHaveBeenLastCalledWith(true);
wrapper.find(GlToggle).vm.$emit(event, false);
expect(listener).toHaveBeenCalledTimes(2);
expect(listener).toHaveBeenLastCalledWith(false);
});
});
describe('with custom options', () => {
const name = 'toggle-name';
const help = 'Help text';
const foo = 'bar';
beforeEach(() => {
initToggleWithOptions({
name,
isChecked: true,
disabled: true,
isLoading: true,
help,
labelPosition: 'hidden',
foo,
});
toggleWrapper = document.querySelector(TOGGLE_WRAPPER_CLASS);
});
it('sets the custom name', () => {
const input = toggleWrapper.querySelector('input[type="hidden"]');
expect(input.name).toBe(name);
});
it('is checked', () => {
expect(toggleWrapper.querySelector(CHECKED_CLASS)).not.toBe(null);
});
it('is disabled', () => {
expect(toggleWrapper.querySelector(DISABLED_CLASS)).not.toBe(null);
});
it('is loading', () => {
expect(toggleWrapper.querySelector(LOADING_CLASS)).not.toBe(null);
});
it('sets the custom help text', () => {
expect(toggleWrapper.querySelector(HELP_TEXT_SELECTOR).textContent).toBe(help);
});
it('hides the label', () => {
expect(
toggleWrapper.querySelector(TOGGLE_LABEL_CLASS).classList.contains('gl-sr-only'),
).toBe(true);
});
it('passes custom dataset to the wrapper', () => {
expect(toggleWrapper.dataset.foo).toBe('bar');
});
});
});
});
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'shared/_gl_toggle.html.haml' do
context 'defaults' do
before do
render partial: 'shared/gl_toggle', locals: {
classes: '.js-gl-toggle'
}
end
it 'does not set a name' do
expect(rendered).not_to have_selector('[data-name]')
end
it 'sets default is-checked attributes' do
expect(rendered).to have_selector('[data-is-checked="false"]')
end
it 'sets default disabled attributes' do
expect(rendered).to have_selector('[data-disabled="false"]')
end
it 'sets default is-loading attributes' do
expect(rendered).to have_selector('[data-is-loading="false"]')
end
it 'does not set a label' do
expect(rendered).not_to have_selector('[data-label]')
end
it 'does not set a label position' do
expect(rendered).not_to have_selector('[data-label-position]')
end
end
context 'with custom options' do
before do
render partial: 'shared/gl_toggle', locals: {
classes: 'js-custom-gl-toggle',
name: 'toggle-name',
is_checked: true,
disabled: true,
is_loading: true,
label: 'Custom label',
label_position: 'top',
data: {
foo: 'bar'
}
}
end
it 'sets the custom class' do
expect(rendered).to have_selector('.js-custom-gl-toggle')
end
it 'sets the custom name' do
expect(rendered).to have_selector('[data-name="toggle-name"]')
end
it 'sets the custom is-checked attributes' do
expect(rendered).to have_selector('[data-is-checked="true"]')
end
it 'sets the custom disabled attributes' do
expect(rendered).to have_selector('[data-disabled="true"]')
end
it 'sets the custom is-loading attributes' do
expect(rendered).to have_selector('[data-is-loading="true"]')
end
it 'sets the custom label' do
expect(rendered).to have_selector('[data-label="Custom label"]')
end
it 'sets the cutom label position' do
expect(rendered).to have_selector('[data-label-position="top"]')
end
it 'sets cutom data attributes' do
expect(rendered).to have_selector('[data-foo="bar"]')
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment