test(editor): SSO tests (#5946)
* test(editor): SSO tests * test(editor): move store tests to __tests__ folder * test(editor): move tests in a different PR * test(editor): add SSO tests * test(editor): add SSO settings page tests * test(editor): add SSO onboarding page base test * test(editor): add SSO onboarding page test * test(editor): fix router spy
This commit is contained in:
@@ -112,7 +112,7 @@ onBeforeMount(async () => {
|
||||
</template>
|
||||
</i18n>
|
||||
</n8n-info-tip>
|
||||
<div v-if="ssoStore.isEnterpriseSamlEnabled">
|
||||
<div v-if="ssoStore.isEnterpriseSamlEnabled" data-testid="sso-content-licensed">
|
||||
<div :class="$style.group">
|
||||
<label>{{ locale.baseText('settings.sso.settings.redirectUrl.label') }}</label>
|
||||
<CopyInput
|
||||
@@ -135,20 +135,26 @@ onBeforeMount(async () => {
|
||||
</div>
|
||||
<div :class="$style.group">
|
||||
<label>{{ locale.baseText('settings.sso.settings.ips.label') }}</label>
|
||||
<n8n-input v-model="metadata" type="textarea" />
|
||||
<n8n-input v-model="metadata" type="textarea" name="metadata" />
|
||||
<small>{{ locale.baseText('settings.sso.settings.ips.help') }}</small>
|
||||
</div>
|
||||
<div :class="$style.buttons">
|
||||
<n8n-button :disabled="!ssoSettingsSaved" type="tertiary" @click="onTest">
|
||||
<n8n-button
|
||||
:disabled="!ssoSettingsSaved"
|
||||
type="tertiary"
|
||||
@click="onTest"
|
||||
data-testid="sso-test"
|
||||
>
|
||||
{{ locale.baseText('settings.sso.settings.test') }}
|
||||
</n8n-button>
|
||||
<n8n-button :disabled="!metadata" @click="onSave">
|
||||
<n8n-button :disabled="!metadata" @click="onSave" data-testid="sso-save">
|
||||
{{ locale.baseText('settings.sso.settings.save') }}
|
||||
</n8n-button>
|
||||
</div>
|
||||
</div>
|
||||
<n8n-action-box
|
||||
v-else
|
||||
data-testid="sso-content-unlicensed"
|
||||
:class="$style.actionBox"
|
||||
:description="locale.baseText('settings.sso.actionBox.description')"
|
||||
:buttonText="locale.baseText('settings.sso.actionBox.buttonText')"
|
||||
|
||||
49
packages/editor-ui/src/views/__tests__/AuthView.test.ts
Normal file
49
packages/editor-ui/src/views/__tests__/AuthView.test.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { render } from '@testing-library/vue';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { merge } from 'lodash-es';
|
||||
import AuthView from '@/views/AuthView.vue';
|
||||
|
||||
const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
||||
render(
|
||||
AuthView,
|
||||
merge(
|
||||
{
|
||||
pinia: createTestingPinia(),
|
||||
stubs: {
|
||||
SSOLogin: {
|
||||
template: '<div data-testid="sso-login"></div>',
|
||||
},
|
||||
},
|
||||
},
|
||||
renderOptions,
|
||||
),
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
|
||||
describe('AuthView', () => {
|
||||
it('should render with subtitle', () => {
|
||||
const { getByText } = renderComponent({
|
||||
props: {
|
||||
subtitle: 'Some text',
|
||||
},
|
||||
});
|
||||
expect(getByText('Some text')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render without SSO component', () => {
|
||||
const { queryByTestId } = renderComponent();
|
||||
expect(queryByTestId('sso-login')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render with SSO component', () => {
|
||||
const { getByTestId } = renderComponent({
|
||||
props: {
|
||||
withSso: true,
|
||||
},
|
||||
});
|
||||
expect(getByTestId('sso-login')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { render } from '@testing-library/vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { useRouter } from 'vue-router/composables';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { merge } from 'lodash-es';
|
||||
import SamlOnboarding from '@/views/SamlOnboarding.vue';
|
||||
import { useSSOStore } from '@/stores/sso';
|
||||
import { STORES } from '@/constants';
|
||||
import { SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/utils/testUtils';
|
||||
import { i18nInstance } from '@/plugins/i18n';
|
||||
|
||||
vi.mock('vue-router/composables', () => {
|
||||
const push = vi.fn();
|
||||
return {
|
||||
useRouter: () => ({
|
||||
push,
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
let pinia: ReturnType<typeof createTestingPinia>;
|
||||
let ssoStore: ReturnType<typeof useSSOStore>;
|
||||
let router: ReturnType<typeof useRouter>;
|
||||
|
||||
const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
||||
render(
|
||||
SamlOnboarding,
|
||||
merge(
|
||||
{
|
||||
pinia,
|
||||
i18n: i18nInstance,
|
||||
},
|
||||
renderOptions,
|
||||
),
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
|
||||
describe('SamlOnboarding', () => {
|
||||
beforeEach(() => {
|
||||
pinia = createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings),
|
||||
},
|
||||
},
|
||||
});
|
||||
ssoStore = useSSOStore(pinia);
|
||||
router = useRouter();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should submit filled in form only and redirect', async () => {
|
||||
vi.spyOn(ssoStore, 'updateUser').mockResolvedValue({
|
||||
id: '1',
|
||||
isPending: false,
|
||||
});
|
||||
|
||||
const { getByRole, getAllByRole } = renderComponent();
|
||||
|
||||
const inputs = getAllByRole('textbox');
|
||||
const submit = getByRole('button');
|
||||
|
||||
await userEvent.click(submit);
|
||||
await waitAllPromises();
|
||||
|
||||
expect(ssoStore.updateUser).not.toHaveBeenCalled();
|
||||
expect(router.push).not.toHaveBeenCalled();
|
||||
|
||||
await userEvent.type(inputs[0], 'test');
|
||||
await userEvent.type(inputs[1], 'test');
|
||||
await userEvent.click(submit);
|
||||
|
||||
expect(ssoStore.updateUser).toHaveBeenCalled();
|
||||
expect(router.push).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
115
packages/editor-ui/src/views/__tests__/SettingsSso.test.ts
Normal file
115
packages/editor-ui/src/views/__tests__/SettingsSso.test.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import { PiniaVuePlugin } from 'pinia';
|
||||
import { render } from '@testing-library/vue';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { merge } from 'lodash-es';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import SettingsSso from '@/views/SettingsSso.vue';
|
||||
import { useSSOStore } from '@/stores/sso';
|
||||
import { STORES } from '@/constants';
|
||||
import { SETTINGS_STORE_DEFAULT_STATE, waitAllPromises } from '@/utils/testUtils';
|
||||
import { i18nInstance } from '@/plugins/i18n';
|
||||
import { SamlPreferences, SamlPreferencesExtractedData } from '@/Interface';
|
||||
|
||||
let pinia: ReturnType<typeof createTestingPinia>;
|
||||
let ssoStore: ReturnType<typeof useSSOStore>;
|
||||
|
||||
const samlConfig: SamlPreferences & SamlPreferencesExtractedData = {
|
||||
metadata: '<?xml version="1.0"?>',
|
||||
entityID: faker.internet.url(),
|
||||
returnUrl: faker.internet.url(),
|
||||
};
|
||||
|
||||
const renderComponent = (renderOptions: Parameters<typeof render>[1] = {}) =>
|
||||
render(
|
||||
SettingsSso,
|
||||
merge(
|
||||
{
|
||||
pinia,
|
||||
i18n: i18nInstance,
|
||||
},
|
||||
renderOptions,
|
||||
),
|
||||
(vue) => {
|
||||
vue.use(PiniaVuePlugin);
|
||||
},
|
||||
);
|
||||
|
||||
describe('SettingsSso', () => {
|
||||
beforeEach(() => {
|
||||
pinia = createTestingPinia({
|
||||
initialState: {
|
||||
[STORES.SETTINGS]: {
|
||||
settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings),
|
||||
},
|
||||
},
|
||||
});
|
||||
ssoStore = useSSOStore(pinia);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should render paywall state when there is no license', () => {
|
||||
const { getByTestId, queryByTestId, queryByRole } = renderComponent();
|
||||
|
||||
expect(queryByRole('checkbox')).not.toBeInTheDocument();
|
||||
expect(queryByTestId('sso-content-licensed')).not.toBeInTheDocument();
|
||||
expect(getByTestId('sso-content-unlicensed')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render licensed content', () => {
|
||||
vi.spyOn(ssoStore, 'isEnterpriseSamlEnabled', 'get').mockReturnValue(true);
|
||||
|
||||
const { getByTestId, queryByTestId, getByRole } = renderComponent();
|
||||
|
||||
expect(getByRole('checkbox')).toBeInTheDocument();
|
||||
expect(getByTestId('sso-content-licensed')).toBeInTheDocument();
|
||||
expect(queryByTestId('sso-content-unlicensed')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should enable activation checkbox and test button if data is already saved', async () => {
|
||||
vi.spyOn(ssoStore, 'isEnterpriseSamlEnabled', 'get').mockReturnValue(true);
|
||||
vi.spyOn(ssoStore, 'getSamlConfig').mockResolvedValue(samlConfig);
|
||||
|
||||
const { getByRole, getByTestId } = renderComponent();
|
||||
await waitAllPromises();
|
||||
|
||||
expect(getByRole('checkbox')).toBeEnabled();
|
||||
expect(getByTestId('sso-test')).toBeEnabled();
|
||||
});
|
||||
|
||||
it('should enable activation checkbox after data is saved', async () => {
|
||||
vi.spyOn(ssoStore, 'isEnterpriseSamlEnabled', 'get').mockReturnValue(true);
|
||||
|
||||
const { getByRole, getAllByRole, getByTestId } = renderComponent();
|
||||
const checkbox = getByRole('checkbox');
|
||||
const btnSave = getByTestId('sso-save');
|
||||
const btnTest = getByTestId('sso-test');
|
||||
|
||||
expect(checkbox).toBeDisabled();
|
||||
[btnSave, btnTest].forEach((el) => {
|
||||
expect(el).toBeDisabled();
|
||||
});
|
||||
|
||||
await userEvent.type(
|
||||
getAllByRole('textbox').find((el) => el.getAttribute('name') === 'metadata')!,
|
||||
'<?xml version="1.0"?>',
|
||||
);
|
||||
|
||||
expect(checkbox).toBeDisabled();
|
||||
expect(btnTest).toBeDisabled();
|
||||
expect(btnSave).toBeEnabled();
|
||||
|
||||
const saveSpy = vi.spyOn(ssoStore, 'saveSamlConfig');
|
||||
const getSpy = vi.spyOn(ssoStore, 'getSamlConfig').mockResolvedValue(samlConfig);
|
||||
await userEvent.click(btnSave);
|
||||
|
||||
expect(saveSpy).toHaveBeenCalled();
|
||||
expect(getSpy).toHaveBeenCalled();
|
||||
expect(checkbox).toBeEnabled();
|
||||
expect(btnTest).toBeEnabled();
|
||||
expect(btnSave).toBeEnabled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user