import { html, fixture, expect, waitUntil } from '@open-wc/testing';
import sinon from 'sinon';
import './login-view';
import { LoginView } from './login-view';
describe('LoginView', () => {
let element: LoginView;
let fetchStub: any;
beforeEach(async () => {
// Set up minimal BRAND_CONFIG for getBrandConfig()
(window as any).BRAND_CONFIG = {
name: 'Test Brand',
domain: 'test.example.com',
company: { legal_name: 'Test Co', address: '123 Test', city: 'Test' },
branding: {
logo_light: '/logo.svg',
logo_dark: '/logo-dark.svg',
favicon: '/favicon.ico',
primary_color: '#000',
gradient_product: '',
gradient_ai: '',
},
social: { twitter: '', linkedin: '', instagram: '' },
};
element = await fixture(html`<login-view></login-view>`);
// Clear localStorage before each test
localStorage.clear();
// Stub fetch before each test
fetchStub = sinon.stub(window, 'fetch');
});
afterEach(() => {
// Restore fetch after each test
fetchStub.restore();
// Clean up BRAND_CONFIG
delete (window as any).BRAND_CONFIG;
});
it('should render the login form', () => {
const form = element.shadowRoot?.querySelector('form');
expect(form).to.exist;
const usernameInput = element.shadowRoot?.querySelector('#username');
expect(usernameInput).to.exist;
const passwordInput = element.shadowRoot?.querySelector('#password');
expect(passwordInput).to.exist;
const loginButton = element.shadowRoot?.querySelector(
'sl-button[type="submit"]'
);
expect(loginButton).to.exist;
});
it('should show an error message on failed login', async () => {
// Stub fetch to simulate a failed login with error detail
fetchStub.resolves(
new Response(JSON.stringify({ detail: 'Invalid credentials' }), {
status: 401,
})
);
// Fill in the form fields
const usernameInput = element.shadowRoot?.querySelector<any>('#username');
const passwordInput = element.shadowRoot?.querySelector<any>('#password');
usernameInput.value = 'testuser';
passwordInput.value = 'wrongpassword';
const form = element.shadowRoot?.querySelector('form') as HTMLFormElement;
const submitEvent = new SubmitEvent('submit', {
bubbles: true,
cancelable: true,
});
form.dispatchEvent(submitEvent);
// Wait until the error message appears in the DOM
await waitUntil(
() => element.shadowRoot?.querySelector('.error-message'),
'Error message did not appear'
);
const errorMessage = element.shadowRoot?.querySelector('.error-message');
expect(errorMessage).to.exist;
expect(errorMessage?.textContent).to.contain('Invalid credentials');
expect(fetchStub).to.have.been.calledOnce;
});
it('should not show an error message on successful login', async () => {
// Stub fetch to simulate a successful login
fetchStub.resolves(
new Response(JSON.stringify({ access_token: 'test_token' }), {
status: 200,
})
);
// Fill in the form fields
const usernameInput = element.shadowRoot?.querySelector<any>('#username');
const passwordInput = element.shadowRoot?.querySelector<any>('#password');
usernameInput.value = 'testuser';
passwordInput.value = 'correctpassword';
const form = element.shadowRoot?.querySelector('form') as HTMLFormElement;
const submitEvent = new SubmitEvent('submit', {
bubbles: true,
cancelable: true,
});
form.dispatchEvent(submitEvent);
// Wait for the async operation to complete
await new Promise((resolve) => setTimeout(resolve, 100));
await element.updateComplete;
// Check that no error message appears
const errorMessage = element.shadowRoot?.querySelector('.error-message');
expect(errorMessage).to.not.exist;
// Verify fetch was called
expect(fetchStub).to.have.been.calledOnce;
// Verify token was stored in localStorage
expect(localStorage.getItem('accessToken')).to.equal('test_token');
});
it('should have links for password reset and registration', () => {
const forgotPasswordLink = element.shadowRoot?.querySelector(
'a[href="/forgot-password"]'
);
expect(forgotPasswordLink).to.exist;
const signUpLink = element.shadowRoot?.querySelector('a[href="/register"]');
expect(signUpLink).to.exist;
});
});