fix: convert Vue emits to @Emit decorator and resolve linting errors
- Replace emits arrays with @Emit decorator in vue-facing-decorator components - Convert ActivityListItem, ContactInputForm, ContactBulkActions, ContactListHeader, MembersList, LargeIdenticonModal, and ContactListItem to use @Emit pattern - Fix TypeScript errors for unused variables and parameters in test files - Remove unused createTestProps function from ProjectIcon.test.ts - Prefix unused wrapper parameters with underscore in componentTestUtils.ts - Replace generic Function type with specific function signatures in testHelpers.ts - All 288 unit tests pass with no regressions - Resolve all 13+ linting errors while maintaining 194 pre-existing warnings This refactoring improves type safety and follows vue-facing-decorator best practices for event emission while maintaining full backward compatibility.
This commit is contained in:
@@ -55,10 +55,7 @@
|
||||
aria-label="Delete profile image"
|
||||
@click="deleteImage"
|
||||
>
|
||||
<font-awesome
|
||||
icon="trash-can"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<font-awesome icon="trash-can" aria-hidden="true" />
|
||||
</button>
|
||||
</span>
|
||||
<div v-else class="text-center">
|
||||
|
||||
@@ -973,28 +973,28 @@ export async function importFromMnemonic(
|
||||
if (isTestUser0) {
|
||||
// Set up Test User #0 specific settings with enhanced error handling
|
||||
const platformService = await getPlatformService();
|
||||
|
||||
|
||||
try {
|
||||
// First, ensure the DID-specific settings record exists
|
||||
await platformService.insertDidSpecificSettings(newId.did);
|
||||
|
||||
|
||||
// Then update with Test User #0 specific settings
|
||||
await platformService.updateDidSpecificSettings(newId.did, {
|
||||
firstName: "User Zero",
|
||||
isRegistered: true,
|
||||
});
|
||||
|
||||
|
||||
// Verify the settings were saved correctly
|
||||
const verificationResult = await platformService.dbQuery(
|
||||
"SELECT firstName, isRegistered FROM settings WHERE accountDid = ?",
|
||||
[newId.did],
|
||||
);
|
||||
|
||||
|
||||
if (verificationResult?.values?.length) {
|
||||
const settings = verificationResult.values[0];
|
||||
const firstName = settings[0];
|
||||
const isRegistered = settings[1];
|
||||
|
||||
|
||||
logger.info("[importFromMnemonic] Test User #0 settings verification", {
|
||||
did: newId.did,
|
||||
firstName,
|
||||
@@ -1002,40 +1002,50 @@ export async function importFromMnemonic(
|
||||
expectedFirstName: "User Zero",
|
||||
expectedIsRegistered: true,
|
||||
});
|
||||
|
||||
|
||||
// If settings weren't saved correctly, try individual updates
|
||||
if (firstName !== "User Zero" || isRegistered !== 1) {
|
||||
logger.warn("[importFromMnemonic] Test User #0 settings not saved correctly, retrying with individual updates");
|
||||
|
||||
logger.warn(
|
||||
"[importFromMnemonic] Test User #0 settings not saved correctly, retrying with individual updates",
|
||||
);
|
||||
|
||||
await platformService.dbExec(
|
||||
"UPDATE settings SET firstName = ? WHERE accountDid = ?",
|
||||
["User Zero", newId.did],
|
||||
);
|
||||
|
||||
|
||||
await platformService.dbExec(
|
||||
"UPDATE settings SET isRegistered = ? WHERE accountDid = ?",
|
||||
[1, newId.did],
|
||||
);
|
||||
|
||||
|
||||
// Verify again
|
||||
const retryResult = await platformService.dbQuery(
|
||||
"SELECT firstName, isRegistered FROM settings WHERE accountDid = ?",
|
||||
[newId.did],
|
||||
);
|
||||
|
||||
|
||||
if (retryResult?.values?.length) {
|
||||
const retrySettings = retryResult.values[0];
|
||||
logger.info("[importFromMnemonic] Test User #0 settings after retry", {
|
||||
firstName: retrySettings[0],
|
||||
isRegistered: retrySettings[1],
|
||||
});
|
||||
logger.info(
|
||||
"[importFromMnemonic] Test User #0 settings after retry",
|
||||
{
|
||||
firstName: retrySettings[0],
|
||||
isRegistered: retrySettings[1],
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.error("[importFromMnemonic] Failed to verify Test User #0 settings - no record found");
|
||||
logger.error(
|
||||
"[importFromMnemonic] Failed to verify Test User #0 settings - no record found",
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("[importFromMnemonic] Error setting up Test User #0 settings:", error);
|
||||
logger.error(
|
||||
"[importFromMnemonic] Error setting up Test User #0 settings:",
|
||||
error,
|
||||
);
|
||||
// Don't throw - allow the import to continue even if settings fail
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +1,36 @@
|
||||
/**
|
||||
* ContactListItem Component Tests
|
||||
*
|
||||
*
|
||||
* Comprehensive test suite for the ContactListItem component.
|
||||
* Tests component rendering, props, events, and user interactions.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import ContactListItem from '@/components/ContactListItem.vue'
|
||||
import { createStandardMockContact } from '@/test/factories/contactFactory'
|
||||
import {
|
||||
createComponentWrapper,
|
||||
testLifecycleEvents,
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import ContactListItem from "@/components/ContactListItem.vue";
|
||||
import { createStandardMockContact } from "@/test/factories/contactFactory";
|
||||
import {
|
||||
createComponentWrapper,
|
||||
testLifecycleEvents,
|
||||
testPerformance,
|
||||
testAccessibility,
|
||||
testErrorHandling
|
||||
} from '@/test/utils/componentTestUtils'
|
||||
testErrorHandling,
|
||||
} from "@/test/utils/componentTestUtils";
|
||||
|
||||
describe('ContactListItem', () => {
|
||||
let wrapper: any
|
||||
describe("ContactListItem", () => {
|
||||
let wrapper: any;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = null
|
||||
})
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
const mountComponent = (props = {}) => {
|
||||
return mount(ContactListItem, {
|
||||
props: {
|
||||
contact: createStandardMockContact(),
|
||||
activeDid: 'did:ethr:test:active',
|
||||
activeDid: "did:ethr:test:active",
|
||||
showCheckbox: false,
|
||||
showActions: false,
|
||||
isSelected: false,
|
||||
@@ -42,404 +42,422 @@ describe('ContactListItem', () => {
|
||||
givenByMeDescriptions: {},
|
||||
givenByMeConfirmed: {},
|
||||
givenByMeUnconfirmed: {},
|
||||
...props
|
||||
...props,
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
EntityIcon: {
|
||||
template: '<div class="entity-icon-stub">EntityIcon</div>',
|
||||
props: ['contact', 'iconSize']
|
||||
props: ["contact", "iconSize"],
|
||||
},
|
||||
'font-awesome': {
|
||||
template: '<span class="font-awesome-stub">FontAwesome</span>'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
"font-awesome": {
|
||||
template: '<span class="font-awesome-stub">FontAwesome</span>',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
describe('Component Rendering', () => {
|
||||
it('should render with correct structure when all props are provided', () => {
|
||||
wrapper = mountComponent()
|
||||
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
expect(wrapper.find('[data-testid="contactListItem"]').exists()).toBe(true)
|
||||
expect(wrapper.find('.entity-icon-stub').exists()).toBe(true)
|
||||
expect(wrapper.find('h2').exists()).toBe(true)
|
||||
})
|
||||
describe("Component Rendering", () => {
|
||||
it("should render with correct structure when all props are provided", () => {
|
||||
wrapper = mountComponent();
|
||||
|
||||
it('should display contact name correctly', () => {
|
||||
const contact = createStandardMockContact({ name: 'Test Contact' })
|
||||
wrapper = mountComponent({ contact })
|
||||
|
||||
expect(wrapper.find('h2').text().replace(/\u00A0/g, ' ')).toContain('Test Contact')
|
||||
})
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(wrapper.find('[data-testid="contactListItem"]').exists()).toBe(
|
||||
true,
|
||||
);
|
||||
expect(wrapper.find(".entity-icon-stub").exists()).toBe(true);
|
||||
expect(wrapper.find("h2").exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should display contact DID correctly', () => {
|
||||
const contact = createStandardMockContact({ did: 'did:ethr:test:123' })
|
||||
wrapper = mountComponent({ contact })
|
||||
|
||||
expect(wrapper.text()).toContain('did:ethr:test:123')
|
||||
})
|
||||
it("should display contact name correctly", () => {
|
||||
const contact = createStandardMockContact({ name: "Test Contact" });
|
||||
wrapper = mountComponent({ contact });
|
||||
|
||||
it('should display contact notes when available', () => {
|
||||
const contact = createStandardMockContact({ notes: 'Test notes' })
|
||||
wrapper = mountComponent({ contact })
|
||||
|
||||
expect(wrapper.text()).toContain('Test notes')
|
||||
})
|
||||
})
|
||||
expect(
|
||||
wrapper
|
||||
.find("h2")
|
||||
.text()
|
||||
.replace(/\u00A0/g, " "),
|
||||
).toContain("Test Contact");
|
||||
});
|
||||
|
||||
describe('Checkbox Functionality', () => {
|
||||
it('should show checkbox when showCheckbox is true', () => {
|
||||
wrapper = mountComponent({ showCheckbox: true })
|
||||
|
||||
expect(wrapper.find('[data-testid="contactCheckOne"]').exists()).toBe(true)
|
||||
})
|
||||
it("should display contact DID correctly", () => {
|
||||
const contact = createStandardMockContact({ did: "did:ethr:test:123" });
|
||||
wrapper = mountComponent({ contact });
|
||||
|
||||
it('should not show checkbox when showCheckbox is false', () => {
|
||||
wrapper = mountComponent({ showCheckbox: false })
|
||||
|
||||
expect(wrapper.find('[data-testid="contactCheckOne"]').exists()).toBe(false)
|
||||
})
|
||||
expect(wrapper.text()).toContain("did:ethr:test:123");
|
||||
});
|
||||
|
||||
it('should emit toggle-selection event when checkbox is clicked', () => {
|
||||
const contact = createStandardMockContact({ did: 'did:ethr:test:123' })
|
||||
wrapper = mountComponent({ showCheckbox: true, contact })
|
||||
|
||||
wrapper.find('[data-testid="contactCheckOne"]').trigger('click')
|
||||
|
||||
expect(wrapper.emitted('toggle-selection')).toBeTruthy()
|
||||
expect(wrapper.emitted('toggle-selection')[0]).toEqual(['did:ethr:test:123'])
|
||||
})
|
||||
it("should display contact notes when available", () => {
|
||||
const contact = createStandardMockContact({ notes: "Test notes" });
|
||||
wrapper = mountComponent({ contact });
|
||||
|
||||
it('should reflect isSelected prop in checkbox state', () => {
|
||||
wrapper = mountComponent({ showCheckbox: true, isSelected: true })
|
||||
|
||||
const checkbox = wrapper.find('[data-testid="contactCheckOne"]')
|
||||
expect(checkbox.attributes('checked')).toBeDefined()
|
||||
})
|
||||
})
|
||||
expect(wrapper.text()).toContain("Test notes");
|
||||
});
|
||||
});
|
||||
|
||||
describe('Actions Section', () => {
|
||||
it('should show actions when showActions is true and contact is not active', () => {
|
||||
wrapper = mountComponent({
|
||||
showActions: true,
|
||||
contact: createStandardMockContact({ did: 'did:ethr:test:other' })
|
||||
})
|
||||
|
||||
expect(wrapper.find('[data-testid="offerButton"]').exists()).toBe(true)
|
||||
})
|
||||
describe("Checkbox Functionality", () => {
|
||||
it("should show checkbox when showCheckbox is true", () => {
|
||||
wrapper = mountComponent({ showCheckbox: true });
|
||||
|
||||
it('should not show actions when contact is active', () => {
|
||||
const contact = createStandardMockContact({ did: 'did:ethr:test:active' })
|
||||
wrapper = mountComponent({
|
||||
showActions: true,
|
||||
expect(wrapper.find('[data-testid="contactCheckOne"]').exists()).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it("should not show checkbox when showCheckbox is false", () => {
|
||||
wrapper = mountComponent({ showCheckbox: false });
|
||||
|
||||
expect(wrapper.find('[data-testid="contactCheckOne"]').exists()).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it("should emit toggle-selection event when checkbox is clicked", () => {
|
||||
const contact = createStandardMockContact({ did: "did:ethr:test:123" });
|
||||
wrapper = mountComponent({ showCheckbox: true, contact });
|
||||
|
||||
wrapper.find('[data-testid="contactCheckOne"]').trigger("click");
|
||||
|
||||
expect(wrapper.emitted("toggle-selection")).toBeTruthy();
|
||||
expect(wrapper.emitted("toggle-selection")[0]).toEqual([
|
||||
"did:ethr:test:123",
|
||||
]);
|
||||
});
|
||||
|
||||
it("should reflect isSelected prop in checkbox state", () => {
|
||||
wrapper = mountComponent({ showCheckbox: true, isSelected: true });
|
||||
|
||||
const checkbox = wrapper.find('[data-testid="contactCheckOne"]');
|
||||
expect(checkbox.attributes("checked")).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Actions Section", () => {
|
||||
it("should show actions when showActions is true and contact is not active", () => {
|
||||
wrapper = mountComponent({
|
||||
showActions: true,
|
||||
contact: createStandardMockContact({ did: "did:ethr:test:other" }),
|
||||
});
|
||||
|
||||
expect(wrapper.find('[data-testid="offerButton"]').exists()).toBe(true);
|
||||
});
|
||||
|
||||
it("should not show actions when contact is active", () => {
|
||||
const contact = createStandardMockContact({
|
||||
did: "did:ethr:test:active",
|
||||
});
|
||||
wrapper = mountComponent({
|
||||
showActions: true,
|
||||
contact,
|
||||
activeDid: 'did:ethr:test:active'
|
||||
})
|
||||
|
||||
expect(wrapper.find('[data-testid="offerButton"]').exists()).toBe(false)
|
||||
})
|
||||
activeDid: "did:ethr:test:active",
|
||||
});
|
||||
|
||||
it('should emit show-identicon event when EntityIcon is clicked', () => {
|
||||
const contact = createStandardMockContact()
|
||||
wrapper = mountComponent({ contact })
|
||||
|
||||
wrapper.find('.entity-icon-stub').trigger('click')
|
||||
|
||||
expect(wrapper.emitted('show-identicon')).toBeTruthy()
|
||||
expect(wrapper.emitted('show-identicon')[0]).toEqual([contact])
|
||||
})
|
||||
expect(wrapper.find('[data-testid="offerButton"]').exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('should emit open-offer-dialog event when offer button is clicked', () => {
|
||||
const contact = createStandardMockContact({
|
||||
did: 'did:ethr:test:123',
|
||||
name: 'Test Contact'
|
||||
})
|
||||
wrapper = mountComponent({
|
||||
showActions: true,
|
||||
contact: createStandardMockContact({ did: 'did:ethr:test:other' })
|
||||
})
|
||||
|
||||
wrapper.find('[data-testid="offerButton"]').trigger('click')
|
||||
|
||||
expect(wrapper.emitted('open-offer-dialog')).toBeTruthy()
|
||||
expect(wrapper.emitted('open-offer-dialog')[0][0]).toBe('did:ethr:test:other')
|
||||
})
|
||||
})
|
||||
it("should emit show-identicon event when EntityIcon is clicked", () => {
|
||||
const contact = createStandardMockContact();
|
||||
wrapper = mountComponent({ contact });
|
||||
|
||||
describe('Give Amounts Display', () => {
|
||||
it('should display give amounts correctly for given to me', () => {
|
||||
const contact = createStandardMockContact({ did: 'did:ethr:test:123' })
|
||||
wrapper.find(".entity-icon-stub").trigger("click");
|
||||
|
||||
expect(wrapper.emitted("show-identicon")).toBeTruthy();
|
||||
expect(wrapper.emitted("show-identicon")[0]).toEqual([contact]);
|
||||
});
|
||||
|
||||
it("should emit open-offer-dialog event when offer button is clicked", () => {
|
||||
wrapper = mountComponent({
|
||||
showActions: true,
|
||||
contact: createStandardMockContact({ did: "did:ethr:test:other" }),
|
||||
});
|
||||
|
||||
wrapper.find('[data-testid="offerButton"]').trigger("click");
|
||||
|
||||
expect(wrapper.emitted("open-offer-dialog")).toBeTruthy();
|
||||
expect(wrapper.emitted("open-offer-dialog")[0][0]).toBe(
|
||||
"did:ethr:test:other",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Give Amounts Display", () => {
|
||||
it("should display give amounts correctly for given to me", () => {
|
||||
const contact = createStandardMockContact({ did: "did:ethr:test:123" });
|
||||
wrapper = mountComponent({
|
||||
contact,
|
||||
showActions: true,
|
||||
givenToMeConfirmed: { 'did:ethr:test:123': 50 },
|
||||
givenToMeUnconfirmed: { 'did:ethr:test:123': 25 }
|
||||
})
|
||||
|
||||
const buttons = wrapper.findAll('button')
|
||||
givenToMeConfirmed: { "did:ethr:test:123": 50 },
|
||||
givenToMeUnconfirmed: { "did:ethr:test:123": 25 },
|
||||
});
|
||||
|
||||
const buttons = wrapper.findAll("button");
|
||||
if (buttons.length > 0) {
|
||||
expect(buttons[0].text()).toBe('75') // 50 + 25
|
||||
expect(buttons[0].text()).toBe("75"); // 50 + 25
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it('should display give amounts correctly for given by me', () => {
|
||||
const contact = createStandardMockContact({ did: 'did:ethr:test:123' })
|
||||
it("should display give amounts correctly for given by me", () => {
|
||||
const contact = createStandardMockContact({ did: "did:ethr:test:123" });
|
||||
wrapper = mountComponent({
|
||||
contact,
|
||||
showActions: true,
|
||||
givenByMeConfirmed: { 'did:ethr:test:123': 30 },
|
||||
givenByMeUnconfirmed: { 'did:ethr:test:123': 20 }
|
||||
})
|
||||
|
||||
const buttons = wrapper.findAll('button')
|
||||
if (buttons.length > 1) {
|
||||
expect(buttons[1].text()).toBe('50') // 30 + 20
|
||||
}
|
||||
})
|
||||
givenByMeConfirmed: { "did:ethr:test:123": 30 },
|
||||
givenByMeUnconfirmed: { "did:ethr:test:123": 20 },
|
||||
});
|
||||
|
||||
it('should show only confirmed amounts when showGiveConfirmed is true', () => {
|
||||
const contact = createStandardMockContact({ did: 'did:ethr:test:123' })
|
||||
const buttons = wrapper.findAll("button");
|
||||
if (buttons.length > 1) {
|
||||
expect(buttons[1].text()).toBe("50"); // 30 + 20
|
||||
}
|
||||
});
|
||||
|
||||
it("should show only confirmed amounts when showGiveConfirmed is true", () => {
|
||||
const contact = createStandardMockContact({ did: "did:ethr:test:123" });
|
||||
wrapper = mountComponent({
|
||||
contact,
|
||||
showActions: true,
|
||||
showGiveTotals: false,
|
||||
showGiveConfirmed: true,
|
||||
givenToMeConfirmed: { 'did:ethr:test:123': 50 },
|
||||
givenToMeUnconfirmed: { 'did:ethr:test:123': 25 }
|
||||
})
|
||||
|
||||
const buttons = wrapper.findAll('button')
|
||||
if (buttons.length > 0) {
|
||||
expect(buttons[0].text()).toBe('50') // Only confirmed
|
||||
}
|
||||
})
|
||||
givenToMeConfirmed: { "did:ethr:test:123": 50 },
|
||||
givenToMeUnconfirmed: { "did:ethr:test:123": 25 },
|
||||
});
|
||||
|
||||
it('should show only unconfirmed amounts when showGiveConfirmed is false', () => {
|
||||
const contact = createStandardMockContact({ did: 'did:ethr:test:123' })
|
||||
const buttons = wrapper.findAll("button");
|
||||
if (buttons.length > 0) {
|
||||
expect(buttons[0].text()).toBe("50"); // Only confirmed
|
||||
}
|
||||
});
|
||||
|
||||
it("should show only unconfirmed amounts when showGiveConfirmed is false", () => {
|
||||
const contact = createStandardMockContact({ did: "did:ethr:test:123" });
|
||||
wrapper = mountComponent({
|
||||
contact,
|
||||
showActions: true,
|
||||
showGiveTotals: false,
|
||||
showGiveConfirmed: false,
|
||||
givenToMeConfirmed: { 'did:ethr:test:123': 50 },
|
||||
givenToMeUnconfirmed: { 'did:ethr:test:123': 25 }
|
||||
})
|
||||
|
||||
const buttons = wrapper.findAll('button')
|
||||
givenToMeConfirmed: { "did:ethr:test:123": 50 },
|
||||
givenToMeUnconfirmed: { "did:ethr:test:123": 25 },
|
||||
});
|
||||
|
||||
const buttons = wrapper.findAll("button");
|
||||
if (buttons.length > 0) {
|
||||
expect(buttons[0].text()).toBe('25') // Only unconfirmed
|
||||
expect(buttons[0].text()).toBe("25"); // Only unconfirmed
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Error Handling', () => {
|
||||
it('should handle undefined contact name gracefully', () => {
|
||||
const contact = createStandardMockContact({ name: undefined })
|
||||
wrapper = mountComponent({ contact })
|
||||
|
||||
expect(wrapper.find('h2').text().replace(/\u00A0/g, ' ')).toContain('(no name)')
|
||||
})
|
||||
describe("Error Handling", () => {
|
||||
it("should handle undefined contact name gracefully", () => {
|
||||
const contact = createStandardMockContact({ name: undefined });
|
||||
wrapper = mountComponent({ contact });
|
||||
|
||||
it('should handle missing give amounts gracefully', () => {
|
||||
const contact = createStandardMockContact({ did: 'did:ethr:test:123' })
|
||||
expect(
|
||||
wrapper
|
||||
.find("h2")
|
||||
.text()
|
||||
.replace(/\u00A0/g, " "),
|
||||
).toContain("(no name)");
|
||||
});
|
||||
|
||||
it("should handle missing give amounts gracefully", () => {
|
||||
const contact = createStandardMockContact({ did: "did:ethr:test:123" });
|
||||
wrapper = mountComponent({
|
||||
contact,
|
||||
showActions: true,
|
||||
givenToMeConfirmed: {},
|
||||
givenToMeUnconfirmed: {},
|
||||
givenByMeConfirmed: {},
|
||||
givenByMeUnconfirmed: {}
|
||||
})
|
||||
|
||||
const buttons = wrapper.findAll('button')
|
||||
givenByMeUnconfirmed: {},
|
||||
});
|
||||
|
||||
const buttons = wrapper.findAll("button");
|
||||
if (buttons.length > 0) {
|
||||
expect(buttons[0].text()).toBe('0')
|
||||
expect(buttons[0].text()).toBe("0");
|
||||
}
|
||||
if (buttons.length > 1) {
|
||||
expect(buttons[1].text()).toBe('0')
|
||||
expect(buttons[1].text()).toBe("0");
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it("should handle rapid prop changes gracefully", () => {
|
||||
wrapper = mountComponent();
|
||||
|
||||
it('should handle rapid prop changes gracefully', () => {
|
||||
wrapper = mountComponent()
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
wrapper.setProps({
|
||||
isSelected: i % 2 === 0,
|
||||
showCheckbox: i % 3 === 0,
|
||||
showActions: i % 4 === 0
|
||||
})
|
||||
showActions: i % 4 === 0,
|
||||
});
|
||||
}
|
||||
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Performance Testing', () => {
|
||||
it('should render within performance threshold', () => {
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Performance Testing", () => {
|
||||
it("should render within performance threshold", () => {
|
||||
const performanceResult = testPerformance(() => {
|
||||
mountComponent()
|
||||
}, 50)
|
||||
|
||||
expect(performanceResult.passed).toBe(true)
|
||||
expect(performanceResult.duration).toBeLessThan(50)
|
||||
})
|
||||
mountComponent();
|
||||
}, 50);
|
||||
|
||||
it('should handle multiple re-renders efficiently', () => {
|
||||
wrapper = mountComponent()
|
||||
|
||||
const start = performance.now()
|
||||
expect(performanceResult.passed).toBe(true);
|
||||
expect(performanceResult.duration).toBeLessThan(50);
|
||||
});
|
||||
|
||||
it("should handle multiple re-renders efficiently", () => {
|
||||
wrapper = mountComponent();
|
||||
|
||||
const start = performance.now();
|
||||
for (let i = 0; i < 50; i++) {
|
||||
wrapper.setProps({ isSelected: i % 2 === 0 })
|
||||
wrapper.setProps({ isSelected: i % 2 === 0 });
|
||||
}
|
||||
const end = performance.now()
|
||||
|
||||
expect(end - start).toBeLessThan(200)
|
||||
})
|
||||
const end = performance.now();
|
||||
|
||||
it('should establish performance baseline', () => {
|
||||
const start = performance.now()
|
||||
wrapper = mountComponent()
|
||||
const end = performance.now()
|
||||
|
||||
console.log('Performance Baseline:', {
|
||||
renderTime: end - start
|
||||
})
|
||||
|
||||
expect(end - start).toBeLessThan(100)
|
||||
})
|
||||
})
|
||||
expect(end - start).toBeLessThan(200);
|
||||
});
|
||||
|
||||
describe('Integration Testing', () => {
|
||||
it('should integrate with EntityIcon component correctly', () => {
|
||||
const contact = createStandardMockContact()
|
||||
wrapper = mountComponent({ contact })
|
||||
|
||||
const entityIcon = wrapper.find('.entity-icon-stub')
|
||||
expect(entityIcon.exists()).toBe(true)
|
||||
})
|
||||
it("should establish performance baseline", () => {
|
||||
const start = performance.now();
|
||||
wrapper = mountComponent();
|
||||
const end = performance.now();
|
||||
|
||||
console.log("Performance Baseline:", {
|
||||
renderTime: end - start,
|
||||
});
|
||||
|
||||
expect(end - start).toBeLessThan(100);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Integration Testing", () => {
|
||||
it("should integrate with EntityIcon component correctly", () => {
|
||||
const contact = createStandardMockContact();
|
||||
wrapper = mountComponent({ contact });
|
||||
|
||||
const entityIcon = wrapper.find(".entity-icon-stub");
|
||||
expect(entityIcon.exists()).toBe(true);
|
||||
});
|
||||
|
||||
it("should handle multiple concurrent events", () => {
|
||||
wrapper = mountComponent({ showCheckbox: true, showActions: true });
|
||||
|
||||
it('should handle multiple concurrent events', () => {
|
||||
wrapper = mountComponent({ showCheckbox: true, showActions: true })
|
||||
|
||||
// Simulate multiple rapid interactions
|
||||
wrapper.find('[data-testid="contactCheckOne"]').trigger('click')
|
||||
wrapper.find('.entity-icon-stub').trigger('click')
|
||||
wrapper.find('[data-testid="offerButton"]').trigger('click')
|
||||
|
||||
expect(wrapper.emitted('toggle-selection')).toBeTruthy()
|
||||
expect(wrapper.emitted('show-identicon')).toBeTruthy()
|
||||
expect(wrapper.emitted('open-offer-dialog')).toBeTruthy()
|
||||
})
|
||||
})
|
||||
wrapper.find('[data-testid="contactCheckOne"]').trigger("click");
|
||||
wrapper.find(".entity-icon-stub").trigger("click");
|
||||
wrapper.find('[data-testid="offerButton"]').trigger("click");
|
||||
|
||||
describe('Snapshot Testing', () => {
|
||||
it('should maintain consistent DOM structure', () => {
|
||||
wrapper = mountComponent()
|
||||
const html = wrapper.html()
|
||||
|
||||
expect(html).toMatch(/<li[^>]*class="[^"]*border-b[^"]*"[^>]*>/)
|
||||
expect(html).toMatch(/<div[^>]*class="[^"]*flex[^"]*"[^>]*>/)
|
||||
expect(html).toContain('EntityIcon')
|
||||
expect(html).toContain('data-testid="contactListItem"')
|
||||
})
|
||||
expect(wrapper.emitted("toggle-selection")).toBeTruthy();
|
||||
expect(wrapper.emitted("show-identicon")).toBeTruthy();
|
||||
expect(wrapper.emitted("open-offer-dialog")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should maintain consistent structure with different prop combinations', () => {
|
||||
describe("Snapshot Testing", () => {
|
||||
it("should maintain consistent DOM structure", () => {
|
||||
wrapper = mountComponent();
|
||||
const html = wrapper.html();
|
||||
|
||||
expect(html).toMatch(/<li[^>]*class="[^"]*border-b[^"]*"[^>]*>/);
|
||||
expect(html).toMatch(/<div[^>]*class="[^"]*flex[^"]*"[^>]*>/);
|
||||
expect(html).toContain("EntityIcon");
|
||||
expect(html).toContain('data-testid="contactListItem"');
|
||||
});
|
||||
|
||||
it("should maintain consistent structure with different prop combinations", () => {
|
||||
const propCombinations = [
|
||||
{ showCheckbox: true, showActions: false },
|
||||
{ showCheckbox: false, showActions: true },
|
||||
{ showCheckbox: true, showActions: true },
|
||||
{ showCheckbox: false, showActions: false }
|
||||
]
|
||||
{ showCheckbox: false, showActions: false },
|
||||
];
|
||||
|
||||
propCombinations.forEach((props) => {
|
||||
const testWrapper = mountComponent(props);
|
||||
const html = testWrapper.html();
|
||||
|
||||
expect(html).toMatch(/<li[^>]*class="[^"]*border-b[^"]*"[^>]*>/);
|
||||
expect(html).toContain("EntityIcon");
|
||||
|
||||
propCombinations.forEach(props => {
|
||||
const testWrapper = mountComponent(props)
|
||||
const html = testWrapper.html()
|
||||
|
||||
expect(html).toMatch(/<li[^>]*class="[^"]*border-b[^"]*"[^>]*>/)
|
||||
expect(html).toContain('EntityIcon')
|
||||
|
||||
if (props.showCheckbox) {
|
||||
expect(html).toContain('data-testid="contactCheckOne"')
|
||||
expect(html).toContain('data-testid="contactCheckOne"');
|
||||
} else {
|
||||
expect(html).not.toContain('data-testid="contactCheckOne"')
|
||||
expect(html).not.toContain('data-testid="contactCheckOne"');
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Accessibility Testing', () => {
|
||||
it('should meet WCAG accessibility standards', () => {
|
||||
wrapper = mountComponent()
|
||||
const listItem = wrapper.find('[data-testid="contactListItem"]')
|
||||
const checkbox = wrapper.find('[data-testid="contactCheckOne"]')
|
||||
const offerButton = wrapper.find('[data-testid="offerButton"]')
|
||||
describe("Accessibility Testing", () => {
|
||||
it("should meet WCAG accessibility standards", () => {
|
||||
wrapper = mountComponent();
|
||||
const listItem = wrapper.find('[data-testid="contactListItem"]');
|
||||
const checkbox = wrapper.find('[data-testid="contactCheckOne"]');
|
||||
const offerButton = wrapper.find('[data-testid="offerButton"]');
|
||||
|
||||
// Semantic structure
|
||||
expect(listItem.exists()).toBe(true)
|
||||
expect(listItem.element.tagName.toLowerCase()).toBe('li')
|
||||
expect(listItem.exists()).toBe(true);
|
||||
expect(listItem.element.tagName.toLowerCase()).toBe("li");
|
||||
|
||||
// Form control accessibility
|
||||
if (checkbox.exists()) {
|
||||
expect(checkbox.attributes('type')).toBe('checkbox')
|
||||
expect(checkbox.attributes("type")).toBe("checkbox");
|
||||
}
|
||||
|
||||
// Button accessibility
|
||||
if (offerButton.exists()) {
|
||||
expect(offerButton.text()).toBe('Offer')
|
||||
expect(offerButton.text()).toBe("Offer");
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
it("should support keyboard navigation", () => {
|
||||
wrapper = mountComponent({ showCheckbox: true, showActions: true });
|
||||
|
||||
const checkbox = wrapper.find('[data-testid="contactCheckOne"]');
|
||||
const offerButton = wrapper.find('[data-testid="offerButton"]');
|
||||
|
||||
it('should support keyboard navigation', () => {
|
||||
wrapper = mountComponent({ showCheckbox: true, showActions: true })
|
||||
|
||||
const checkbox = wrapper.find('[data-testid="contactCheckOne"]')
|
||||
const offerButton = wrapper.find('[data-testid="offerButton"]')
|
||||
|
||||
// Test that controls are clickable (supports keyboard navigation)
|
||||
expect(checkbox.exists()).toBe(true)
|
||||
expect(offerButton.exists()).toBe(true)
|
||||
|
||||
checkbox.trigger('click')
|
||||
expect(wrapper.emitted('toggle-selection')).toBeTruthy()
|
||||
|
||||
offerButton.trigger('click')
|
||||
expect(wrapper.emitted('open-offer-dialog')).toBeTruthy()
|
||||
})
|
||||
expect(checkbox.exists()).toBe(true);
|
||||
expect(offerButton.exists()).toBe(true);
|
||||
|
||||
it('should have descriptive content', () => {
|
||||
const contact = createStandardMockContact({ name: 'Test Contact' })
|
||||
wrapper = mountComponent({ contact })
|
||||
|
||||
expect(wrapper.text().replace(/\u00A0/g, ' ')).toContain('Test Contact')
|
||||
expect(wrapper.text()).toContain('did:ethr:test')
|
||||
})
|
||||
checkbox.trigger("click");
|
||||
expect(wrapper.emitted("toggle-selection")).toBeTruthy();
|
||||
|
||||
it('should maintain accessibility with different prop combinations', () => {
|
||||
offerButton.trigger("click");
|
||||
expect(wrapper.emitted("open-offer-dialog")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should have descriptive content", () => {
|
||||
const contact = createStandardMockContact({ name: "Test Contact" });
|
||||
wrapper = mountComponent({ contact });
|
||||
|
||||
expect(wrapper.text().replace(/\u00A0/g, " ")).toContain("Test Contact");
|
||||
expect(wrapper.text()).toContain("did:ethr:test");
|
||||
});
|
||||
|
||||
it("should maintain accessibility with different prop combinations", () => {
|
||||
const testCases = [
|
||||
{ showCheckbox: true, showActions: false },
|
||||
{ showCheckbox: false, showActions: true },
|
||||
{ showCheckbox: true, showActions: true }
|
||||
]
|
||||
{ showCheckbox: true, showActions: true },
|
||||
];
|
||||
|
||||
testCases.forEach(props => {
|
||||
const testWrapper = mountComponent(props)
|
||||
const listItem = testWrapper.find('[data-testid="contactListItem"]')
|
||||
|
||||
expect(listItem.exists()).toBe(true)
|
||||
expect(testWrapper.find('.entity-icon-stub').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
testCases.forEach((props) => {
|
||||
const testWrapper = mountComponent(props);
|
||||
const listItem = testWrapper.find('[data-testid="contactListItem"]');
|
||||
|
||||
describe('Centralized Utility Testing', () => {
|
||||
it('should use centralized component wrapper', () => {
|
||||
expect(listItem.exists()).toBe(true);
|
||||
expect(testWrapper.find(".entity-icon-stub").exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Centralized Utility Testing", () => {
|
||||
it("should use centralized component wrapper", () => {
|
||||
const wrapperFactory = createComponentWrapper(ContactListItem, {
|
||||
contact: createStandardMockContact(),
|
||||
activeDid: 'did:ethr:test:active',
|
||||
activeDid: "did:ethr:test:active",
|
||||
showCheckbox: false,
|
||||
showActions: false,
|
||||
isSelected: false,
|
||||
@@ -450,68 +468,74 @@ describe('ContactListItem', () => {
|
||||
givenToMeUnconfirmed: {},
|
||||
givenByMeDescriptions: {},
|
||||
givenByMeConfirmed: {},
|
||||
givenByMeUnconfirmed: {}
|
||||
})
|
||||
|
||||
const testWrapper = wrapperFactory()
|
||||
expect(testWrapper.exists()).toBe(true)
|
||||
expect(testWrapper.find('[data-testid="contactListItem"]').exists()).toBe(true)
|
||||
})
|
||||
givenByMeUnconfirmed: {},
|
||||
});
|
||||
|
||||
it('should test lifecycle events using centralized utilities', async () => {
|
||||
wrapper = mountComponent()
|
||||
const results = await testLifecycleEvents(wrapper, ['mounted', 'updated'])
|
||||
|
||||
expect(results).toHaveLength(2)
|
||||
expect(results.every(r => r.success)).toBe(true)
|
||||
})
|
||||
const testWrapper = wrapperFactory();
|
||||
expect(testWrapper.exists()).toBe(true);
|
||||
expect(testWrapper.find('[data-testid="contactListItem"]').exists()).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it('should test performance using centralized utilities', () => {
|
||||
it("should test lifecycle events using centralized utilities", async () => {
|
||||
wrapper = mountComponent();
|
||||
const results = await testLifecycleEvents(wrapper, [
|
||||
"mounted",
|
||||
"updated",
|
||||
]);
|
||||
|
||||
expect(results).toHaveLength(2);
|
||||
expect(results.every((r) => r.success)).toBe(true);
|
||||
});
|
||||
|
||||
it("should test performance using centralized utilities", () => {
|
||||
const performanceResult = testPerformance(() => {
|
||||
mountComponent()
|
||||
}, 50)
|
||||
|
||||
expect(performanceResult.passed).toBe(true)
|
||||
expect(performanceResult.duration).toBeLessThan(50)
|
||||
})
|
||||
mountComponent();
|
||||
}, 50);
|
||||
|
||||
it('should test accessibility using centralized utilities', () => {
|
||||
wrapper = mountComponent()
|
||||
expect(performanceResult.passed).toBe(true);
|
||||
expect(performanceResult.duration).toBeLessThan(50);
|
||||
});
|
||||
|
||||
it("should test accessibility using centralized utilities", () => {
|
||||
wrapper = mountComponent();
|
||||
const accessibilityChecks = [
|
||||
{
|
||||
name: 'has list item',
|
||||
test: (wrapper: any) => wrapper.find('[data-testid="contactListItem"]').exists()
|
||||
name: "has list item",
|
||||
test: (wrapper: any) =>
|
||||
wrapper.find('[data-testid="contactListItem"]').exists(),
|
||||
},
|
||||
{
|
||||
name: 'has entity icon',
|
||||
test: (wrapper: any) => wrapper.find('.entity-icon-stub').exists()
|
||||
name: "has entity icon",
|
||||
test: (wrapper: any) => wrapper.find(".entity-icon-stub").exists(),
|
||||
},
|
||||
{
|
||||
name: 'has contact name',
|
||||
test: (wrapper: any) => wrapper.find('h2').exists()
|
||||
}
|
||||
]
|
||||
|
||||
const results = testAccessibility(wrapper, accessibilityChecks)
|
||||
expect(results).toHaveLength(3)
|
||||
expect(results.every(r => r.success && r.passed)).toBe(true)
|
||||
})
|
||||
name: "has contact name",
|
||||
test: (wrapper: any) => wrapper.find("h2").exists(),
|
||||
},
|
||||
];
|
||||
|
||||
it('should test error handling using centralized utilities', async () => {
|
||||
wrapper = mountComponent()
|
||||
const results = testAccessibility(wrapper, accessibilityChecks);
|
||||
expect(results).toHaveLength(3);
|
||||
expect(results.every((r) => r.success && r.passed)).toBe(true);
|
||||
});
|
||||
|
||||
it("should test error handling using centralized utilities", async () => {
|
||||
wrapper = mountComponent();
|
||||
const errorScenarios = [
|
||||
{
|
||||
name: 'invalid props',
|
||||
name: "invalid props",
|
||||
action: async (wrapper: any) => {
|
||||
await wrapper.setProps({ isSelected: 'invalid' as any })
|
||||
await wrapper.setProps({ isSelected: "invalid" as any });
|
||||
},
|
||||
expectedBehavior: 'should handle gracefully'
|
||||
}
|
||||
]
|
||||
|
||||
const results = await testErrorHandling(wrapper, errorScenarios)
|
||||
expect(results).toHaveLength(1)
|
||||
expect(results.every(r => r.success)).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
expectedBehavior: "should handle gracefully",
|
||||
},
|
||||
];
|
||||
|
||||
const results = await testErrorHandling(wrapper, errorScenarios);
|
||||
expect(results).toHaveLength(1);
|
||||
expect(results.every((r) => r.success)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,16 +3,18 @@
|
||||
<h2>PlatformServiceMixin Test</h2>
|
||||
<button @click="testInsert">Test Insert</button>
|
||||
<button @click="testUpdate">Test Update</button>
|
||||
<button
|
||||
:class="primaryButtonClasses"
|
||||
@click="testUserZeroSettings"
|
||||
>
|
||||
<button :class="primaryButtonClasses" @click="testUserZeroSettings">
|
||||
Test User #0 Settings
|
||||
</button>
|
||||
|
||||
<div v-if="userZeroTestResult" class="mt-4 p-4 border border-gray-300 rounded-md bg-gray-50">
|
||||
<div
|
||||
v-if="userZeroTestResult"
|
||||
class="mt-4 p-4 border border-gray-300 rounded-md bg-gray-50"
|
||||
>
|
||||
<h4 class="font-semibold mb-2">User #0 Settings Test Result:</h4>
|
||||
<pre class="text-sm">{{ JSON.stringify(userZeroTestResult, null, 2) }}</pre>
|
||||
<pre class="text-sm">{{
|
||||
JSON.stringify(userZeroTestResult, null, 2)
|
||||
}}</pre>
|
||||
</div>
|
||||
<pre>{{ result }}</pre>
|
||||
</div>
|
||||
@@ -55,16 +57,16 @@ export default class PlatformServiceMixinTest extends Vue {
|
||||
try {
|
||||
// User #0's DID
|
||||
const userZeroDid = "did:ethr:0x0000694B58C2cC69658993A90D3840C560f2F51F";
|
||||
|
||||
|
||||
this.result = "Testing User #0 settings...";
|
||||
|
||||
|
||||
// Test the debug methods
|
||||
await this.$debugMergedSettings(userZeroDid);
|
||||
|
||||
|
||||
// Get the actual settings
|
||||
const didSettings = await this.$debugDidSettings(userZeroDid);
|
||||
const accountSettings = await this.$accountSettings(userZeroDid);
|
||||
|
||||
|
||||
this.userZeroTestResult = {
|
||||
didSettings,
|
||||
accountSettings,
|
||||
@@ -72,7 +74,7 @@ export default class PlatformServiceMixinTest extends Vue {
|
||||
firstName: accountSettings.firstName,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
||||
|
||||
this.result = `User #0 settings test completed. isRegistered: ${accountSettings.isRegistered}`;
|
||||
} catch (error) {
|
||||
this.result = `Error testing User #0 settings: ${error}`;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,11 +2,11 @@ import { Component, Vue, Prop } from "vue-facing-decorator";
|
||||
|
||||
/**
|
||||
* ContactBulkActions Mock Component
|
||||
*
|
||||
*
|
||||
* A mock implementation of the ContactBulkActions component for testing purposes.
|
||||
* Provides the same interface as the original component but with simplified behavior
|
||||
* for unit testing scenarios.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
@Component({ name: "ContactBulkActions" })
|
||||
@@ -53,7 +53,7 @@ export default class ContactBulkActionsMock extends Vue {
|
||||
* @returns void
|
||||
*/
|
||||
mockToggleAllSelection(): void {
|
||||
this.$emit('toggle-all-selection');
|
||||
this.$emit("toggle-all-selection");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +61,7 @@ export default class ContactBulkActionsMock extends Vue {
|
||||
* @returns void
|
||||
*/
|
||||
mockCopySelected(): void {
|
||||
this.$emit('copy-selected');
|
||||
this.$emit("copy-selected");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,4 +79,4 @@ export default class ContactBulkActionsMock extends Vue {
|
||||
get checkboxTestId(): string {
|
||||
return "contactCheckAllBottom";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,11 @@ import { Contact } from "../../db/tables/contacts";
|
||||
|
||||
/**
|
||||
* LargeIdenticonModal Mock Component
|
||||
*
|
||||
*
|
||||
* A mock implementation of the LargeIdenticonModal component for testing purposes.
|
||||
* Provides the same interface as the original component but with simplified behavior
|
||||
* for unit testing scenarios.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
@Component({ name: "LargeIdenticonModal" })
|
||||
@@ -51,7 +51,7 @@ export default class LargeIdenticonModalMock extends Vue {
|
||||
* @returns void
|
||||
*/
|
||||
mockClose(): void {
|
||||
this.$emit('close');
|
||||
this.$emit("close");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,4 +61,4 @@ export default class LargeIdenticonModalMock extends Vue {
|
||||
get iconSize(): number {
|
||||
return 512;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ import { Component, Vue, Prop } from "vue-facing-decorator";
|
||||
|
||||
/**
|
||||
* ProjectIcon Mock Component
|
||||
*
|
||||
*
|
||||
* A mock implementation of the ProjectIcon component for testing purposes.
|
||||
* Provides the same interface as the original component but with simplified behavior
|
||||
* for unit testing scenarios.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
@Component({ name: "ProjectIcon" })
|
||||
@@ -85,4 +85,4 @@ export default class ProjectIconMock extends Vue {
|
||||
get shouldUseBlankConfig(): boolean {
|
||||
return !this.entityId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ import { Component, Vue, Prop, Emit } from "vue-facing-decorator";
|
||||
|
||||
/**
|
||||
* RegistrationNotice Mock Component
|
||||
*
|
||||
*
|
||||
* A mock implementation of the RegistrationNotice component for testing purposes.
|
||||
* Provides the same interface as the original component but with simplified behavior
|
||||
* for unit testing scenarios.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
@Component({ name: "RegistrationNotice" })
|
||||
@@ -51,4 +51,4 @@ export default class RegistrationNoticeMock extends Vue {
|
||||
get noticeText(): string {
|
||||
return "Before you can publicly announce a new project or time commitment, a friend needs to register you.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
/**
|
||||
* Centralized Utilities Example
|
||||
*
|
||||
*
|
||||
* Comprehensive example demonstrating how to use all centralized test utilities
|
||||
* for consistent, maintainable component testing.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import RegistrationNotice from '@/components/RegistrationNotice.vue'
|
||||
import { createSimpleMockContact } from '@/test/factories/contactFactory'
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import RegistrationNotice from "@/components/RegistrationNotice.vue";
|
||||
import {
|
||||
createComponentWrapper,
|
||||
createTestDataFactory,
|
||||
@@ -21,296 +20,305 @@ import {
|
||||
testPerformance,
|
||||
testAccessibility,
|
||||
testErrorHandling,
|
||||
createMockEventListeners
|
||||
} from '@/test/utils/componentTestUtils'
|
||||
createMockEventListeners,
|
||||
} from "@/test/utils/componentTestUtils";
|
||||
|
||||
/**
|
||||
* Example: Using Centralized Test Utilities
|
||||
*
|
||||
*
|
||||
* This example demonstrates how to use all the centralized utilities
|
||||
* for comprehensive component testing with consistent patterns.
|
||||
*/
|
||||
describe('Centralized Utilities Example', () => {
|
||||
let wrapper: any
|
||||
describe("Centralized Utilities Example", () => {
|
||||
let wrapper: any;
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = null
|
||||
})
|
||||
wrapper = null;
|
||||
});
|
||||
|
||||
describe('1. Component Wrapper Factory', () => {
|
||||
it('should use centralized component wrapper for consistent mounting', () => {
|
||||
describe("1. Component Wrapper Factory", () => {
|
||||
it("should use centralized component wrapper for consistent mounting", () => {
|
||||
// Create a reusable wrapper factory
|
||||
const wrapperFactory = createComponentWrapper(
|
||||
RegistrationNotice,
|
||||
{ isRegistered: false, show: true },
|
||||
{ stubs: { /* common stubs */ } }
|
||||
)
|
||||
{
|
||||
stubs: {
|
||||
/* common stubs */
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// Use the factory to create test instances
|
||||
const testWrapper = wrapperFactory()
|
||||
expect(testWrapper.exists()).toBe(true)
|
||||
const testWrapper = wrapperFactory();
|
||||
expect(testWrapper.exists()).toBe(true);
|
||||
|
||||
// Create with custom props
|
||||
const customWrapper = wrapperFactory({ show: false })
|
||||
expect(customWrapper.find('#noticeBeforeAnnounce').exists()).toBe(false)
|
||||
})
|
||||
})
|
||||
const customWrapper = wrapperFactory({ show: false });
|
||||
expect(customWrapper.find("#noticeBeforeAnnounce").exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('2. Test Data Factory', () => {
|
||||
it('should use centralized test data factory for consistent data', () => {
|
||||
describe("2. Test Data Factory", () => {
|
||||
it("should use centralized test data factory for consistent data", () => {
|
||||
// Create a test data factory
|
||||
const createTestProps = createTestDataFactory({
|
||||
isRegistered: false,
|
||||
show: true,
|
||||
title: 'Test Notice'
|
||||
})
|
||||
title: "Test Notice",
|
||||
});
|
||||
|
||||
// Use the factory with overrides
|
||||
const props1 = createTestProps()
|
||||
const props2 = createTestProps({ show: false })
|
||||
const props3 = createTestProps({ title: 'Custom Title' })
|
||||
const props1 = createTestProps();
|
||||
const props2 = createTestProps({ show: false });
|
||||
const props3 = createTestProps({ title: "Custom Title" });
|
||||
|
||||
expect(props1.show).toBe(true)
|
||||
expect(props2.show).toBe(false)
|
||||
expect(props3.title).toBe('Custom Title')
|
||||
})
|
||||
})
|
||||
expect(props1.show).toBe(true);
|
||||
expect(props2.show).toBe(false);
|
||||
expect(props3.title).toBe("Custom Title");
|
||||
});
|
||||
});
|
||||
|
||||
describe('3. Async Operations', () => {
|
||||
it('should handle async operations consistently', async () => {
|
||||
describe("3. Async Operations", () => {
|
||||
it("should handle async operations consistently", async () => {
|
||||
wrapper = mount(RegistrationNotice, {
|
||||
props: { isRegistered: false, show: true }
|
||||
})
|
||||
props: { isRegistered: false, show: true },
|
||||
});
|
||||
|
||||
// Wait for async operations to complete
|
||||
await waitForAsync(wrapper, 100)
|
||||
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
expect(wrapper.find('#noticeBeforeAnnounce').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
await waitForAsync(wrapper, 100);
|
||||
|
||||
describe('4. Lifecycle Testing', () => {
|
||||
it('should test component lifecycle events', async () => {
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(wrapper.find("#noticeBeforeAnnounce").exists()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("4. Lifecycle Testing", () => {
|
||||
it("should test component lifecycle events", async () => {
|
||||
wrapper = mount(RegistrationNotice, {
|
||||
props: { isRegistered: false, show: true }
|
||||
})
|
||||
props: { isRegistered: false, show: true },
|
||||
});
|
||||
|
||||
// Test lifecycle events using centralized utilities
|
||||
const results = await testLifecycleEvents(wrapper, ['mounted', 'updated'])
|
||||
const results = await testLifecycleEvents(wrapper, [
|
||||
"mounted",
|
||||
"updated",
|
||||
]);
|
||||
|
||||
expect(results).toHaveLength(2)
|
||||
expect(results.every(r => r.success)).toBe(true)
|
||||
expect(results[0].event).toBe('mounted')
|
||||
expect(results[1].event).toBe('updated')
|
||||
})
|
||||
})
|
||||
expect(results).toHaveLength(2);
|
||||
expect(results.every((r) => r.success)).toBe(true);
|
||||
expect(results[0].event).toBe("mounted");
|
||||
expect(results[1].event).toBe("updated");
|
||||
});
|
||||
});
|
||||
|
||||
describe('5. Computed Properties Testing', () => {
|
||||
it('should test computed properties consistently', () => {
|
||||
describe("5. Computed Properties Testing", () => {
|
||||
it("should test computed properties consistently", () => {
|
||||
wrapper = mount(RegistrationNotice, {
|
||||
props: { isRegistered: false, show: true }
|
||||
})
|
||||
props: { isRegistered: false, show: true },
|
||||
});
|
||||
|
||||
// Test computed properties using centralized utilities
|
||||
const results = testComputedProperties(wrapper, ['vm'])
|
||||
const results = testComputedProperties(wrapper, ["vm"]);
|
||||
|
||||
expect(results).toHaveLength(1)
|
||||
expect(results[0].success).toBe(true)
|
||||
expect(results[0].propName).toBe('vm')
|
||||
})
|
||||
})
|
||||
expect(results).toHaveLength(1);
|
||||
expect(results[0].success).toBe(true);
|
||||
expect(results[0].propName).toBe("vm");
|
||||
});
|
||||
});
|
||||
|
||||
describe('6. Watcher Testing', () => {
|
||||
it('should test component watchers consistently', async () => {
|
||||
describe("6. Watcher Testing", () => {
|
||||
it("should test component watchers consistently", async () => {
|
||||
wrapper = mount(RegistrationNotice, {
|
||||
props: { isRegistered: false, show: true }
|
||||
})
|
||||
props: { isRegistered: false, show: true },
|
||||
});
|
||||
|
||||
// Test watchers using centralized utilities
|
||||
const watcherTests = [
|
||||
{ property: 'show', newValue: false },
|
||||
{ property: 'isRegistered', newValue: true }
|
||||
]
|
||||
{ property: "show", newValue: false },
|
||||
{ property: "isRegistered", newValue: true },
|
||||
];
|
||||
|
||||
const results = await testWatchers(wrapper, watcherTests)
|
||||
const results = await testWatchers(wrapper, watcherTests);
|
||||
|
||||
expect(results).toHaveLength(2)
|
||||
expect(results.every(r => r.success)).toBe(true)
|
||||
expect(results[0].property).toBe('show')
|
||||
expect(results[1].property).toBe('isRegistered')
|
||||
})
|
||||
})
|
||||
expect(results).toHaveLength(2);
|
||||
expect(results.every((r) => r.success)).toBe(true);
|
||||
expect(results[0].property).toBe("show");
|
||||
expect(results[1].property).toBe("isRegistered");
|
||||
});
|
||||
});
|
||||
|
||||
describe('7. Performance Testing', () => {
|
||||
it('should test component performance consistently', () => {
|
||||
describe("7. Performance Testing", () => {
|
||||
it("should test component performance consistently", () => {
|
||||
// Test performance using centralized utilities
|
||||
const performanceResult = testPerformance(() => {
|
||||
mount(RegistrationNotice, {
|
||||
props: { isRegistered: false, show: true }
|
||||
})
|
||||
}, 50)
|
||||
props: { isRegistered: false, show: true },
|
||||
});
|
||||
}, 50);
|
||||
|
||||
expect(performanceResult.passed).toBe(true)
|
||||
expect(performanceResult.duration).toBeLessThan(50)
|
||||
expect(performanceResult.performance).toMatch(/^\d+\.\d+ms$/)
|
||||
})
|
||||
})
|
||||
expect(performanceResult.passed).toBe(true);
|
||||
expect(performanceResult.duration).toBeLessThan(50);
|
||||
expect(performanceResult.performance).toMatch(/^\d+\.\d+ms$/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('8. Accessibility Testing', () => {
|
||||
it('should test accessibility features consistently', () => {
|
||||
describe("8. Accessibility Testing", () => {
|
||||
it("should test accessibility features consistently", () => {
|
||||
wrapper = mount(RegistrationNotice, {
|
||||
props: { isRegistered: false, show: true }
|
||||
})
|
||||
props: { isRegistered: false, show: true },
|
||||
});
|
||||
|
||||
// Test accessibility using centralized utilities
|
||||
const accessibilityChecks = [
|
||||
{
|
||||
name: 'has alert role',
|
||||
test: (wrapper: any) => wrapper.find('[role="alert"]').exists()
|
||||
name: "has alert role",
|
||||
test: (wrapper: any) => wrapper.find('[role="alert"]').exists(),
|
||||
},
|
||||
{
|
||||
name: 'has aria-live',
|
||||
test: (wrapper: any) => wrapper.find('[aria-live="polite"]').exists()
|
||||
name: "has aria-live",
|
||||
test: (wrapper: any) => wrapper.find('[aria-live="polite"]').exists(),
|
||||
},
|
||||
{
|
||||
name: 'has button',
|
||||
test: (wrapper: any) => wrapper.find('button').exists()
|
||||
name: "has button",
|
||||
test: (wrapper: any) => wrapper.find("button").exists(),
|
||||
},
|
||||
{
|
||||
name: 'has correct text',
|
||||
test: (wrapper: any) => wrapper.text().includes('Share Your Info')
|
||||
}
|
||||
]
|
||||
name: "has correct text",
|
||||
test: (wrapper: any) => wrapper.text().includes("Share Your Info"),
|
||||
},
|
||||
];
|
||||
|
||||
const results = testAccessibility(wrapper, accessibilityChecks)
|
||||
const results = testAccessibility(wrapper, accessibilityChecks);
|
||||
|
||||
expect(results).toHaveLength(4)
|
||||
expect(results.every(r => r.success && r.passed)).toBe(true)
|
||||
})
|
||||
})
|
||||
expect(results).toHaveLength(4);
|
||||
expect(results.every((r) => r.success && r.passed)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('9. Error Handling Testing', () => {
|
||||
it('should test error handling consistently', async () => {
|
||||
describe("9. Error Handling Testing", () => {
|
||||
it("should test error handling consistently", async () => {
|
||||
wrapper = mount(RegistrationNotice, {
|
||||
props: { isRegistered: false, show: true }
|
||||
})
|
||||
props: { isRegistered: false, show: true },
|
||||
});
|
||||
|
||||
// Test error handling using centralized utilities
|
||||
const errorScenarios = [
|
||||
{
|
||||
name: 'invalid boolean prop',
|
||||
name: "invalid boolean prop",
|
||||
action: async (wrapper: any) => {
|
||||
await wrapper.setProps({ isRegistered: 'invalid' as any })
|
||||
await wrapper.setProps({ isRegistered: "invalid" as any });
|
||||
},
|
||||
expectedBehavior: 'should handle gracefully'
|
||||
expectedBehavior: "should handle gracefully",
|
||||
},
|
||||
{
|
||||
name: 'null prop',
|
||||
name: "null prop",
|
||||
action: async (wrapper: any) => {
|
||||
await wrapper.setProps({ show: null as any })
|
||||
await wrapper.setProps({ show: null as any });
|
||||
},
|
||||
expectedBehavior: 'should handle gracefully'
|
||||
expectedBehavior: "should handle gracefully",
|
||||
},
|
||||
{
|
||||
name: 'undefined prop',
|
||||
name: "undefined prop",
|
||||
action: async (wrapper: any) => {
|
||||
await wrapper.setProps({ isRegistered: undefined })
|
||||
await wrapper.setProps({ isRegistered: undefined });
|
||||
},
|
||||
expectedBehavior: 'should handle gracefully'
|
||||
}
|
||||
]
|
||||
expectedBehavior: "should handle gracefully",
|
||||
},
|
||||
];
|
||||
|
||||
const results = await testErrorHandling(wrapper, errorScenarios)
|
||||
const results = await testErrorHandling(wrapper, errorScenarios);
|
||||
|
||||
expect(results).toHaveLength(3)
|
||||
expect(results.every(r => r.success)).toBe(true)
|
||||
})
|
||||
})
|
||||
expect(results).toHaveLength(3);
|
||||
expect(results.every((r) => r.success)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('10. Event Listener Testing', () => {
|
||||
it('should create mock event listeners consistently', () => {
|
||||
describe("10. Event Listener Testing", () => {
|
||||
it("should create mock event listeners consistently", () => {
|
||||
// Create mock event listeners
|
||||
const events = ['click', 'keydown', 'focus', 'blur']
|
||||
const listeners = createMockEventListeners(events)
|
||||
const events = ["click", "keydown", "focus", "blur"];
|
||||
const listeners = createMockEventListeners(events);
|
||||
|
||||
expect(Object.keys(listeners)).toHaveLength(4)
|
||||
expect(listeners.click).toBeDefined()
|
||||
expect(listeners.keydown).toBeDefined()
|
||||
expect(listeners.focus).toBeDefined()
|
||||
expect(listeners.blur).toBeDefined()
|
||||
expect(Object.keys(listeners)).toHaveLength(4);
|
||||
expect(listeners.click).toBeDefined();
|
||||
expect(listeners.keydown).toBeDefined();
|
||||
expect(listeners.focus).toBeDefined();
|
||||
expect(listeners.blur).toBeDefined();
|
||||
|
||||
// Test that listeners are callable
|
||||
listeners.click()
|
||||
expect(listeners.click).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
listeners.click();
|
||||
expect(listeners.click).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('11. Comprehensive Integration Example', () => {
|
||||
it('should demonstrate full integration of all utilities', async () => {
|
||||
describe("11. Comprehensive Integration Example", () => {
|
||||
it("should demonstrate full integration of all utilities", async () => {
|
||||
// 1. Create component wrapper factory
|
||||
const wrapperFactory = createComponentWrapper(
|
||||
RegistrationNotice,
|
||||
{ isRegistered: false, show: true }
|
||||
)
|
||||
const wrapperFactory = createComponentWrapper(RegistrationNotice, {
|
||||
isRegistered: false,
|
||||
show: true,
|
||||
});
|
||||
|
||||
// 2. Create test data factory
|
||||
const createTestProps = createTestDataFactory({
|
||||
isRegistered: false,
|
||||
show: true
|
||||
})
|
||||
show: true,
|
||||
});
|
||||
|
||||
// 3. Mount component
|
||||
wrapper = wrapperFactory(createTestProps())
|
||||
wrapper = wrapperFactory(createTestProps());
|
||||
|
||||
// 4. Wait for async operations
|
||||
await waitForAsync(wrapper)
|
||||
await waitForAsync(wrapper);
|
||||
|
||||
// 5. Test lifecycle
|
||||
const lifecycleResults = await testLifecycleEvents(wrapper, ['mounted'])
|
||||
expect(lifecycleResults[0].success).toBe(true)
|
||||
const lifecycleResults = await testLifecycleEvents(wrapper, ["mounted"]);
|
||||
expect(lifecycleResults[0].success).toBe(true);
|
||||
|
||||
// 6. Test computed properties
|
||||
const computedResults = testComputedProperties(wrapper, ['vm'])
|
||||
expect(computedResults[0].success).toBe(true)
|
||||
const computedResults = testComputedProperties(wrapper, ["vm"]);
|
||||
expect(computedResults[0].success).toBe(true);
|
||||
|
||||
// 7. Test watchers
|
||||
const watcherResults = await testWatchers(wrapper, [
|
||||
{ property: 'show', newValue: false }
|
||||
])
|
||||
expect(watcherResults[0].success).toBe(true)
|
||||
{ property: "show", newValue: false },
|
||||
]);
|
||||
expect(watcherResults[0].success).toBe(true);
|
||||
|
||||
// 8. Test performance
|
||||
const performanceResult = testPerformance(() => {
|
||||
wrapper.find('button').trigger('click')
|
||||
}, 10)
|
||||
expect(performanceResult.passed).toBe(true)
|
||||
wrapper.find("button").trigger("click");
|
||||
}, 10);
|
||||
expect(performanceResult.passed).toBe(true);
|
||||
|
||||
// 9. Test accessibility
|
||||
const accessibilityResults = testAccessibility(wrapper, [
|
||||
{
|
||||
name: 'has button',
|
||||
test: (wrapper: any) => wrapper.find('button').exists()
|
||||
}
|
||||
])
|
||||
expect(accessibilityResults[0].success && accessibilityResults[0].passed).toBe(true)
|
||||
name: "has button",
|
||||
test: (wrapper: any) => wrapper.find("button").exists(),
|
||||
},
|
||||
]);
|
||||
expect(
|
||||
accessibilityResults[0].success && accessibilityResults[0].passed,
|
||||
).toBe(true);
|
||||
|
||||
// 10. Test error handling
|
||||
const errorResults = await testErrorHandling(wrapper, [
|
||||
{
|
||||
name: 'invalid prop',
|
||||
name: "invalid prop",
|
||||
action: async (wrapper: any) => {
|
||||
await wrapper.setProps({ isRegistered: 'invalid' as any })
|
||||
await wrapper.setProps({ isRegistered: "invalid" as any });
|
||||
},
|
||||
expectedBehavior: 'should handle gracefully'
|
||||
}
|
||||
])
|
||||
expect(errorResults[0].success).toBe(true)
|
||||
expectedBehavior: "should handle gracefully",
|
||||
},
|
||||
]);
|
||||
expect(errorResults[0].success).toBe(true);
|
||||
|
||||
// 11. Test events
|
||||
const button = wrapper.find('button')
|
||||
button.trigger('click')
|
||||
expect(wrapper.emitted('share-info')).toBeTruthy()
|
||||
})
|
||||
})
|
||||
})
|
||||
const button = wrapper.find("button");
|
||||
button.trigger("click");
|
||||
expect(wrapper.emitted("share-info")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
/**
|
||||
* Enhanced Testing Example
|
||||
*
|
||||
*
|
||||
* Demonstrates how to use the expanded test utilities for comprehensive
|
||||
* component testing with factories, mocks, and assertion helpers.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import {
|
||||
createTestSetup,
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
import { mount } from "@vue/test-utils";
|
||||
import {
|
||||
createTestSetup,
|
||||
createMockApiClient,
|
||||
createMockNotificationService,
|
||||
createMockAuthService,
|
||||
@@ -18,19 +18,18 @@ import {
|
||||
assertionUtils,
|
||||
componentUtils,
|
||||
lifecycleUtils,
|
||||
computedUtils,
|
||||
watcherUtils,
|
||||
eventModifierUtils
|
||||
} from '@/test/utils/testHelpers'
|
||||
import {
|
||||
eventModifierUtils,
|
||||
} from "@/test/utils/testHelpers";
|
||||
import {
|
||||
createSimpleMockContact,
|
||||
createStandardMockContact,
|
||||
createComplexMockContact,
|
||||
createMockProject,
|
||||
createMockAccount,
|
||||
createMockUser,
|
||||
createMockSettings
|
||||
} from '@/test/factories/contactFactory'
|
||||
createMockSettings,
|
||||
} from "@/test/factories/contactFactory";
|
||||
|
||||
/**
|
||||
* Example component for testing
|
||||
@@ -50,338 +49,357 @@ const ExampleComponent = {
|
||||
`,
|
||||
props: {
|
||||
title: { type: String, required: true },
|
||||
description: { type: String, default: '' },
|
||||
buttonText: { type: String, default: 'Click Me' },
|
||||
description: { type: String, default: "" },
|
||||
buttonText: { type: String, default: "Click Me" },
|
||||
showDetails: { type: Boolean, default: false },
|
||||
details: { type: String, default: '' }
|
||||
details: { type: String, default: "" },
|
||||
},
|
||||
emits: ['click', 'details-toggle'],
|
||||
emits: ["click", "details-toggle"],
|
||||
data() {
|
||||
return {
|
||||
clickCount: 0
|
||||
}
|
||||
clickCount: 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
displayTitle() {
|
||||
return this.title.toUpperCase()
|
||||
return this.title.toUpperCase();
|
||||
},
|
||||
hasDescription() {
|
||||
return this.description.length > 0
|
||||
}
|
||||
return this.description.length > 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleClick() {
|
||||
this.clickCount++
|
||||
this.$emit('click', this.clickCount)
|
||||
this.clickCount++;
|
||||
this.$emit("click", this.clickCount);
|
||||
},
|
||||
toggleDetails() {
|
||||
this.$emit('details-toggle', !this.showDetails)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.$emit("details-toggle", !this.showDetails);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe('Enhanced Testing Example', () => {
|
||||
describe("Enhanced Testing Example", () => {
|
||||
const setup = createTestSetup(ExampleComponent, {
|
||||
title: 'Test Component',
|
||||
description: 'Test description'
|
||||
})
|
||||
title: "Test Component",
|
||||
description: "Test description",
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
setup.wrapper = null
|
||||
})
|
||||
setup.wrapper = null;
|
||||
});
|
||||
|
||||
describe('Factory Functions Example', () => {
|
||||
it('should demonstrate contact factory usage', () => {
|
||||
describe("Factory Functions Example", () => {
|
||||
it("should demonstrate contact factory usage", () => {
|
||||
// Simple contact for basic testing
|
||||
const simpleContact = createSimpleMockContact()
|
||||
expect(simpleContact.did).toBeDefined()
|
||||
expect(simpleContact.name).toBeDefined()
|
||||
const simpleContact = createSimpleMockContact();
|
||||
expect(simpleContact.did).toBeDefined();
|
||||
expect(simpleContact.name).toBeDefined();
|
||||
|
||||
// Standard contact for most testing
|
||||
const standardContact = createStandardMockContact()
|
||||
expect(standardContact.contactMethods).toBeDefined()
|
||||
expect(standardContact.notes).toBeDefined()
|
||||
const standardContact = createStandardMockContact();
|
||||
expect(standardContact.contactMethods).toBeDefined();
|
||||
expect(standardContact.notes).toBeDefined();
|
||||
|
||||
// Complex contact for integration testing
|
||||
const complexContact = createComplexMockContact()
|
||||
expect(complexContact.profileImageUrl).toBeDefined()
|
||||
expect(complexContact.publicKeyBase64).toBeDefined()
|
||||
})
|
||||
const complexContact = createComplexMockContact();
|
||||
expect(complexContact.profileImageUrl).toBeDefined();
|
||||
expect(complexContact.publicKeyBase64).toBeDefined();
|
||||
});
|
||||
|
||||
it('should demonstrate other factory functions', () => {
|
||||
const project = createMockProject({ name: 'Test Project' })
|
||||
const account = createMockAccount({ balance: 500.00 })
|
||||
const user = createMockUser({ username: 'testuser' })
|
||||
const settings = createMockSettings({ theme: 'dark' })
|
||||
it("should demonstrate other factory functions", () => {
|
||||
const project = createMockProject({ name: "Test Project" });
|
||||
const account = createMockAccount({ balance: 500.0 });
|
||||
const user = createMockUser({ username: "testuser" });
|
||||
const settings = createMockSettings({ theme: "dark" });
|
||||
|
||||
expect(project.name).toBe('Test Project')
|
||||
expect(account.balance).toBe(500.00)
|
||||
expect(user.username).toBe('testuser')
|
||||
expect(settings.theme).toBe('dark')
|
||||
})
|
||||
})
|
||||
expect(project.name).toBe("Test Project");
|
||||
expect(account.balance).toBe(500.0);
|
||||
expect(user.username).toBe("testuser");
|
||||
expect(settings.theme).toBe("dark");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Mock Services Example", () => {
|
||||
it("should demonstrate API client mocking", () => {
|
||||
const apiClient = createMockApiClient();
|
||||
|
||||
describe('Mock Services Example', () => {
|
||||
it('should demonstrate API client mocking', () => {
|
||||
const apiClient = createMockApiClient()
|
||||
|
||||
// Test API methods
|
||||
expect(apiClient.get).toBeDefined()
|
||||
expect(apiClient.post).toBeDefined()
|
||||
expect(apiClient.put).toBeDefined()
|
||||
expect(apiClient.delete).toBeDefined()
|
||||
})
|
||||
expect(apiClient.get).toBeDefined();
|
||||
expect(apiClient.post).toBeDefined();
|
||||
expect(apiClient.put).toBeDefined();
|
||||
expect(apiClient.delete).toBeDefined();
|
||||
});
|
||||
|
||||
it("should demonstrate notification service mocking", () => {
|
||||
const notificationService = createMockNotificationService();
|
||||
|
||||
it('should demonstrate notification service mocking', () => {
|
||||
const notificationService = createMockNotificationService()
|
||||
|
||||
// Test notification methods
|
||||
expect(notificationService.show).toBeDefined()
|
||||
expect(notificationService.success).toBeDefined()
|
||||
expect(notificationService.error).toBeDefined()
|
||||
})
|
||||
expect(notificationService.show).toBeDefined();
|
||||
expect(notificationService.success).toBeDefined();
|
||||
expect(notificationService.error).toBeDefined();
|
||||
});
|
||||
|
||||
it("should demonstrate auth service mocking", () => {
|
||||
const authService = createMockAuthService();
|
||||
|
||||
it('should demonstrate auth service mocking', () => {
|
||||
const authService = createMockAuthService()
|
||||
|
||||
// Test auth methods
|
||||
expect(authService.login).toBeDefined()
|
||||
expect(authService.logout).toBeDefined()
|
||||
expect(authService.isAuthenticated).toBeDefined()
|
||||
})
|
||||
expect(authService.login).toBeDefined();
|
||||
expect(authService.logout).toBeDefined();
|
||||
expect(authService.isAuthenticated).toBeDefined();
|
||||
});
|
||||
|
||||
it("should demonstrate database service mocking", () => {
|
||||
const dbService = createMockDatabaseService();
|
||||
|
||||
it('should demonstrate database service mocking', () => {
|
||||
const dbService = createMockDatabaseService()
|
||||
|
||||
// Test database methods
|
||||
expect(dbService.query).toBeDefined()
|
||||
expect(dbService.execute).toBeDefined()
|
||||
expect(dbService.transaction).toBeDefined()
|
||||
})
|
||||
})
|
||||
expect(dbService.query).toBeDefined();
|
||||
expect(dbService.execute).toBeDefined();
|
||||
expect(dbService.transaction).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Assertion Utils Example', () => {
|
||||
it('should demonstrate assertion utilities', async () => {
|
||||
describe("Assertion Utils Example", () => {
|
||||
it("should demonstrate assertion utilities", async () => {
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: {
|
||||
title: 'Test Title',
|
||||
description: 'Test Description'
|
||||
}
|
||||
})
|
||||
title: "Test Title",
|
||||
description: "Test Description",
|
||||
},
|
||||
});
|
||||
|
||||
// Assert required props
|
||||
assertionUtils.assertRequiredProps(wrapper, ['title'])
|
||||
assertionUtils.assertRequiredProps(wrapper, ["title"]);
|
||||
|
||||
// Assert CSS classes
|
||||
const button = wrapper.find('button')
|
||||
assertionUtils.assertHasClasses(button, ['btn-primary'])
|
||||
const button = wrapper.find("button");
|
||||
assertionUtils.assertHasClasses(button, ["btn-primary"]);
|
||||
|
||||
// Assert attributes
|
||||
assertionUtils.assertHasAttributes(button, {
|
||||
type: 'button'
|
||||
})
|
||||
type: "button",
|
||||
});
|
||||
|
||||
// Assert accessibility
|
||||
assertionUtils.assertIsAccessible(button)
|
||||
assertionUtils.assertIsAccessible(button);
|
||||
|
||||
// Assert ARIA attributes
|
||||
assertionUtils.assertHasAriaAttributes(button, [])
|
||||
})
|
||||
assertionUtils.assertHasAriaAttributes(button, []);
|
||||
});
|
||||
|
||||
it('should demonstrate performance assertions', async () => {
|
||||
it("should demonstrate performance assertions", async () => {
|
||||
const duration = await assertionUtils.assertPerformance(async () => {
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: { title: 'Performance Test' }
|
||||
})
|
||||
await wrapper.unmount()
|
||||
}, 100)
|
||||
props: { title: "Performance Test" },
|
||||
});
|
||||
await wrapper.unmount();
|
||||
}, 100);
|
||||
|
||||
expect(duration).toBeLessThan(100)
|
||||
})
|
||||
expect(duration).toBeLessThan(100);
|
||||
});
|
||||
|
||||
it('should demonstrate error handling assertions', async () => {
|
||||
it("should demonstrate error handling assertions", async () => {
|
||||
const invalidProps = [
|
||||
{ title: null },
|
||||
{ title: undefined },
|
||||
{ title: 123 },
|
||||
{ title: {} }
|
||||
]
|
||||
{ title: {} },
|
||||
];
|
||||
|
||||
await assertionUtils.assertErrorHandling(ExampleComponent, invalidProps)
|
||||
})
|
||||
await assertionUtils.assertErrorHandling(ExampleComponent, invalidProps);
|
||||
});
|
||||
|
||||
it('should demonstrate accessibility compliance', () => {
|
||||
it("should demonstrate accessibility compliance", () => {
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: { title: 'Accessibility Test' }
|
||||
})
|
||||
props: { title: "Accessibility Test" },
|
||||
});
|
||||
|
||||
assertionUtils.assertAccessibilityCompliance(wrapper)
|
||||
})
|
||||
})
|
||||
assertionUtils.assertAccessibilityCompliance(wrapper);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Component Utils Example', () => {
|
||||
it('should demonstrate prop combination testing', async () => {
|
||||
describe("Component Utils Example", () => {
|
||||
it("should demonstrate prop combination testing", async () => {
|
||||
const propCombinations = [
|
||||
{ title: 'Test 1', showDetails: true },
|
||||
{ title: 'Test 2', showDetails: false },
|
||||
{ title: 'Test 3', description: 'With description' },
|
||||
{ title: 'Test 4', buttonText: 'Custom Button' }
|
||||
]
|
||||
{ title: "Test 1", showDetails: true },
|
||||
{ title: "Test 2", showDetails: false },
|
||||
{ title: "Test 3", description: "With description" },
|
||||
{ title: "Test 4", buttonText: "Custom Button" },
|
||||
];
|
||||
|
||||
const results = await componentUtils.testPropCombinations(
|
||||
ExampleComponent,
|
||||
propCombinations
|
||||
)
|
||||
ExampleComponent,
|
||||
propCombinations,
|
||||
);
|
||||
|
||||
expect(results).toHaveLength(4)
|
||||
expect(results.every(r => r.success)).toBe(true)
|
||||
})
|
||||
expect(results).toHaveLength(4);
|
||||
expect(results.every((r) => r.success)).toBe(true);
|
||||
});
|
||||
|
||||
it('should demonstrate responsive behavior testing', async () => {
|
||||
it("should demonstrate responsive behavior testing", async () => {
|
||||
const results = await componentUtils.testResponsiveBehavior(
|
||||
ExampleComponent,
|
||||
{ title: 'Responsive Test' }
|
||||
)
|
||||
{ title: "Responsive Test" },
|
||||
);
|
||||
|
||||
expect(results).toHaveLength(4) // 4 screen sizes
|
||||
expect(results.every(r => r.rendered)).toBe(true)
|
||||
})
|
||||
expect(results).toHaveLength(4); // 4 screen sizes
|
||||
expect(results.every((r) => r.rendered)).toBe(true);
|
||||
});
|
||||
|
||||
it('should demonstrate theme behavior testing', async () => {
|
||||
const results = await componentUtils.testThemeBehavior(
|
||||
ExampleComponent,
|
||||
{ title: 'Theme Test' }
|
||||
)
|
||||
it("should demonstrate theme behavior testing", async () => {
|
||||
const results = await componentUtils.testThemeBehavior(ExampleComponent, {
|
||||
title: "Theme Test",
|
||||
});
|
||||
|
||||
expect(results).toHaveLength(3) // 3 themes
|
||||
expect(results.every(r => r.rendered)).toBe(true)
|
||||
})
|
||||
expect(results).toHaveLength(3); // 3 themes
|
||||
expect(results.every((r) => r.rendered)).toBe(true);
|
||||
});
|
||||
|
||||
it('should demonstrate internationalization testing', async () => {
|
||||
it("should demonstrate internationalization testing", async () => {
|
||||
const results = await componentUtils.testInternationalization(
|
||||
ExampleComponent,
|
||||
{ title: 'i18n Test' }
|
||||
)
|
||||
{ title: "i18n Test" },
|
||||
);
|
||||
|
||||
expect(results).toHaveLength(4) // 4 languages
|
||||
expect(results.every(r => r.rendered)).toBe(true)
|
||||
})
|
||||
})
|
||||
expect(results).toHaveLength(4); // 4 languages
|
||||
expect(results.every((r) => r.rendered)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Lifecycle Utils Example', () => {
|
||||
it('should demonstrate lifecycle testing', async () => {
|
||||
describe("Lifecycle Utils Example", () => {
|
||||
it("should demonstrate lifecycle testing", async () => {
|
||||
// Test mounting
|
||||
const wrapper = await lifecycleUtils.testMounting(
|
||||
ExampleComponent,
|
||||
{ title: 'Lifecycle Test' }
|
||||
)
|
||||
expect(wrapper.exists()).toBe(true)
|
||||
const wrapper = await lifecycleUtils.testMounting(ExampleComponent, {
|
||||
title: "Lifecycle Test",
|
||||
});
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
|
||||
// Test unmounting
|
||||
await lifecycleUtils.testUnmounting(wrapper)
|
||||
await lifecycleUtils.testUnmounting(wrapper);
|
||||
|
||||
// Test prop updates
|
||||
const mountedWrapper = mount(ExampleComponent, { title: 'Test' })
|
||||
const mountedWrapper = mount(ExampleComponent, { title: "Test" });
|
||||
const propUpdates = [
|
||||
{ props: { title: 'Updated Title' } },
|
||||
{ props: { title: "Updated Title" } },
|
||||
{ props: { showDetails: true } },
|
||||
{ props: { description: 'Updated description' } }
|
||||
]
|
||||
{ props: { description: "Updated description" } },
|
||||
];
|
||||
|
||||
const results = await lifecycleUtils.testPropUpdates(mountedWrapper, propUpdates)
|
||||
expect(results).toHaveLength(3)
|
||||
expect(results.every(r => r.success)).toBe(true)
|
||||
})
|
||||
})
|
||||
const results = await lifecycleUtils.testPropUpdates(
|
||||
mountedWrapper,
|
||||
propUpdates,
|
||||
);
|
||||
expect(results).toHaveLength(3);
|
||||
expect(results.every((r) => r.success)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Computed Utils Example', () => {
|
||||
it('should demonstrate computed property testing', async () => {
|
||||
describe("Computed Utils Example", () => {
|
||||
it("should demonstrate computed property testing", async () => {
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: { title: 'Computed Test' }
|
||||
})
|
||||
props: { title: "Computed Test" },
|
||||
});
|
||||
|
||||
// Test computed property values
|
||||
const vm = wrapper.vm as any
|
||||
expect(vm.displayTitle).toBe('COMPUTED TEST')
|
||||
expect(vm.hasDescription).toBe(false)
|
||||
const vm = wrapper.vm as any;
|
||||
expect(vm.displayTitle).toBe("COMPUTED TEST");
|
||||
expect(vm.hasDescription).toBe(false);
|
||||
|
||||
// Test computed property dependencies
|
||||
await wrapper.setProps({ description: 'New description' })
|
||||
expect(vm.hasDescription).toBe(true)
|
||||
await wrapper.setProps({ description: "New description" });
|
||||
expect(vm.hasDescription).toBe(true);
|
||||
|
||||
// Test computed property caching
|
||||
const firstCall = vm.displayTitle
|
||||
const secondCall = vm.displayTitle
|
||||
expect(firstCall).toBe(secondCall)
|
||||
})
|
||||
})
|
||||
const firstCall = vm.displayTitle;
|
||||
const secondCall = vm.displayTitle;
|
||||
expect(firstCall).toBe(secondCall);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Watcher Utils Example', () => {
|
||||
it('should demonstrate watcher testing', async () => {
|
||||
describe("Watcher Utils Example", () => {
|
||||
it("should demonstrate watcher testing", async () => {
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: { title: 'Watcher Test' }
|
||||
})
|
||||
props: { title: "Watcher Test" },
|
||||
});
|
||||
|
||||
// Test watcher triggers
|
||||
const result = await watcherUtils.testWatcherTrigger(wrapper, 'title', 'New Title')
|
||||
expect(result.triggered).toBe(true)
|
||||
const result = await watcherUtils.testWatcherTrigger(
|
||||
wrapper,
|
||||
"title",
|
||||
"New Title",
|
||||
);
|
||||
expect(result.triggered).toBe(true);
|
||||
|
||||
// Test watcher cleanup
|
||||
const cleanupResult = await watcherUtils.testWatcherCleanup(wrapper)
|
||||
expect(cleanupResult.unmounted).toBe(true)
|
||||
const cleanupResult = await watcherUtils.testWatcherCleanup(wrapper);
|
||||
expect(cleanupResult.unmounted).toBe(true);
|
||||
|
||||
// Test deep watchers
|
||||
const newWrapper = mount(ExampleComponent, { title: 'Deep Test' })
|
||||
const deepResult = await watcherUtils.testDeepWatcher(newWrapper, 'title', 'Deep Title')
|
||||
expect(deepResult.updated).toBe(true)
|
||||
})
|
||||
})
|
||||
const newWrapper = mount(ExampleComponent, { title: "Deep Test" });
|
||||
const deepResult = await watcherUtils.testDeepWatcher(
|
||||
newWrapper,
|
||||
"title",
|
||||
"Deep Title",
|
||||
);
|
||||
expect(deepResult.updated).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Event Modifier Utils Example', () => {
|
||||
it('should demonstrate event modifier testing', async () => {
|
||||
describe("Event Modifier Utils Example", () => {
|
||||
it("should demonstrate event modifier testing", async () => {
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: { title: 'Event Test' }
|
||||
})
|
||||
|
||||
const button = wrapper.find('button')
|
||||
props: { title: "Event Test" },
|
||||
});
|
||||
|
||||
// Test prevent modifier
|
||||
const preventResult = await eventModifierUtils.testPreventModifier(wrapper, 'button')
|
||||
expect(preventResult.eventTriggered).toBe(true)
|
||||
expect(preventResult.preventDefaultCalled).toBe(true)
|
||||
const preventResult = await eventModifierUtils.testPreventModifier(
|
||||
wrapper,
|
||||
"button",
|
||||
);
|
||||
expect(preventResult.eventTriggered).toBe(true);
|
||||
expect(preventResult.preventDefaultCalled).toBe(true);
|
||||
|
||||
// Test stop modifier
|
||||
const stopResult = await eventModifierUtils.testStopModifier(wrapper, 'button')
|
||||
expect(stopResult.eventTriggered).toBe(true)
|
||||
expect(stopResult.stopPropagationCalled).toBe(true)
|
||||
const stopResult = await eventModifierUtils.testStopModifier(
|
||||
wrapper,
|
||||
"button",
|
||||
);
|
||||
expect(stopResult.eventTriggered).toBe(true);
|
||||
expect(stopResult.stopPropagationCalled).toBe(true);
|
||||
|
||||
// Test once modifier
|
||||
const onceResult = await eventModifierUtils.testOnceModifier(wrapper, 'button')
|
||||
expect(onceResult.firstClickEmitted).toBe(true)
|
||||
expect(onceResult.secondClickEmitted).toBe(true)
|
||||
const onceResult = await eventModifierUtils.testOnceModifier(
|
||||
wrapper,
|
||||
"button",
|
||||
);
|
||||
expect(onceResult.firstClickEmitted).toBe(true);
|
||||
expect(onceResult.secondClickEmitted).toBe(true);
|
||||
|
||||
// Test self modifier
|
||||
const selfResult = await eventModifierUtils.testSelfModifier(wrapper, 'button')
|
||||
expect(selfResult.selfClickEmitted).toBe(true)
|
||||
expect(selfResult.childClickEmitted).toBe(true)
|
||||
})
|
||||
})
|
||||
const selfResult = await eventModifierUtils.testSelfModifier(
|
||||
wrapper,
|
||||
"button",
|
||||
);
|
||||
expect(selfResult.selfClickEmitted).toBe(true);
|
||||
expect(selfResult.childClickEmitted).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Integration Example', () => {
|
||||
it('should demonstrate comprehensive testing workflow', async () => {
|
||||
describe("Integration Example", () => {
|
||||
it("should demonstrate comprehensive testing workflow", async () => {
|
||||
// 1. Create test data using factories
|
||||
const contact = createStandardMockContact()
|
||||
const project = createMockProject()
|
||||
const user = createMockUser()
|
||||
const contact = createStandardMockContact();
|
||||
const project = createMockProject();
|
||||
const user = createMockUser();
|
||||
|
||||
// 2. Create mock services
|
||||
const apiClient = createMockApiClient()
|
||||
const notificationService = createMockNotificationService()
|
||||
const authService = createMockAuthService()
|
||||
const apiClient = createMockApiClient();
|
||||
const notificationService = createMockNotificationService();
|
||||
const authService = createMockAuthService();
|
||||
|
||||
// 3. Mount component with mocks
|
||||
const wrapper = mount(ExampleComponent, {
|
||||
props: { title: 'Integration Test' },
|
||||
props: { title: "Integration Test" },
|
||||
global: {
|
||||
provide: {
|
||||
apiClient,
|
||||
@@ -389,29 +407,31 @@ describe('Enhanced Testing Example', () => {
|
||||
authService,
|
||||
contact,
|
||||
project,
|
||||
user
|
||||
}
|
||||
}
|
||||
})
|
||||
user,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// 4. Run comprehensive assertions
|
||||
assertionUtils.assertRequiredProps(wrapper, ['title'])
|
||||
assertionUtils.assertIsAccessible(wrapper.find('button'))
|
||||
assertionUtils.assertAccessibilityCompliance(wrapper)
|
||||
assertionUtils.assertRequiredProps(wrapper, ["title"]);
|
||||
assertionUtils.assertIsAccessible(wrapper.find("button"));
|
||||
assertionUtils.assertAccessibilityCompliance(wrapper);
|
||||
|
||||
// 5. Test lifecycle
|
||||
await lifecycleUtils.testUnmounting(wrapper)
|
||||
await lifecycleUtils.testUnmounting(wrapper);
|
||||
|
||||
// 6. Test performance
|
||||
await assertionUtils.assertPerformance(async () => {
|
||||
const newWrapper = mount(ExampleComponent, { title: 'Performance Test' })
|
||||
await newWrapper.unmount()
|
||||
}, 50)
|
||||
const newWrapper = mount(ExampleComponent, {
|
||||
title: "Performance Test",
|
||||
});
|
||||
await newWrapper.unmount();
|
||||
}, 50);
|
||||
|
||||
// 7. Verify all mocks were used correctly
|
||||
expect(apiClient.get).not.toHaveBeenCalled()
|
||||
expect(notificationService.show).not.toHaveBeenCalled()
|
||||
expect(authService.isAuthenticated).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
expect(apiClient.get).not.toHaveBeenCalled();
|
||||
expect(notificationService.show).not.toHaveBeenCalled();
|
||||
expect(authService.isAuthenticated).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
/**
|
||||
* Contact Factory for TimeSafari Testing
|
||||
*
|
||||
*
|
||||
* Provides different levels of mock contact data for testing
|
||||
* various components and scenarios. Uses dynamic data generation
|
||||
* to avoid hardcoded values and ensure test isolation.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
|
||||
import { Contact, ContactMethod } from '@/db/tables/contacts'
|
||||
import { createTestDataFactory } from '@/test/utils/componentTestUtils'
|
||||
import { Contact, ContactMethod } from "@/db/tables/contacts";
|
||||
|
||||
/**
|
||||
* Create a simple mock contact for basic component testing
|
||||
@@ -18,8 +17,8 @@ import { createTestDataFactory } from '@/test/utils/componentTestUtils'
|
||||
export const createSimpleMockContact = (overrides = {}): Contact => ({
|
||||
did: `did:ethr:test:${Date.now()}`,
|
||||
name: `Test Contact ${Date.now()}`,
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create a standard mock contact for most component testing
|
||||
@@ -29,14 +28,14 @@ export const createStandardMockContact = (overrides = {}): Contact => ({
|
||||
did: `did:ethr:test:${Date.now()}`,
|
||||
name: `Test Contact ${Date.now()}`,
|
||||
contactMethods: [
|
||||
{ label: 'Email', type: 'EMAIL', value: 'test@example.com' },
|
||||
{ label: 'Phone', type: 'SMS', value: '+1234567890' }
|
||||
{ label: "Email", type: "EMAIL", value: "test@example.com" },
|
||||
{ label: "Phone", type: "SMS", value: "+1234567890" },
|
||||
],
|
||||
notes: 'Test contact notes',
|
||||
notes: "Test contact notes",
|
||||
seesMe: true,
|
||||
registered: false,
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create a complex mock contact for integration and service testing
|
||||
@@ -46,19 +45,19 @@ export const createComplexMockContact = (overrides = {}): Contact => ({
|
||||
did: `did:ethr:test:${Date.now()}`,
|
||||
name: `Test Contact ${Date.now()}`,
|
||||
contactMethods: [
|
||||
{ label: 'Email', type: 'EMAIL', value: 'test@example.com' },
|
||||
{ label: 'Phone', type: 'SMS', value: '+1234567890' },
|
||||
{ label: 'WhatsApp', type: 'WHATSAPP', value: '+1234567890' }
|
||||
{ label: "Email", type: "EMAIL", value: "test@example.com" },
|
||||
{ label: "Phone", type: "SMS", value: "+1234567890" },
|
||||
{ label: "WhatsApp", type: "WHATSAPP", value: "+1234567890" },
|
||||
],
|
||||
notes: 'Test contact notes with special characters: éñü',
|
||||
profileImageUrl: 'https://example.com/avatar.jpg',
|
||||
publicKeyBase64: 'base64encodedpublickey',
|
||||
nextPubKeyHashB64: 'base64encodedhash',
|
||||
notes: "Test contact notes with special characters: éñü",
|
||||
profileImageUrl: "https://example.com/avatar.jpg",
|
||||
publicKeyBase64: "base64encodedpublickey",
|
||||
nextPubKeyHashB64: "base64encodedhash",
|
||||
seesMe: true,
|
||||
registered: true,
|
||||
iViewContent: true,
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create multiple contacts for list testing
|
||||
@@ -67,16 +66,16 @@ export const createComplexMockContact = (overrides = {}): Contact => ({
|
||||
* @returns Array of mock contacts
|
||||
*/
|
||||
export const createMockContacts = (
|
||||
count: number,
|
||||
factory = createStandardMockContact
|
||||
count: number,
|
||||
factory = createStandardMockContact,
|
||||
): Contact[] => {
|
||||
return Array.from({ length: count }, (_, index) =>
|
||||
factory({
|
||||
return Array.from({ length: count }, (_, index) =>
|
||||
factory({
|
||||
did: `did:ethr:test:${index + 1}`,
|
||||
name: `Test Contact ${index + 1}`
|
||||
})
|
||||
)
|
||||
}
|
||||
name: `Test Contact ${index + 1}`,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create invalid contact data for error testing
|
||||
@@ -84,40 +83,40 @@ export const createMockContacts = (
|
||||
*/
|
||||
export const createInvalidContacts = (): Partial<Contact>[] => [
|
||||
{},
|
||||
{ did: '' },
|
||||
{ did: 'invalid-did' },
|
||||
{ did: 'did:ethr:test', name: null as any },
|
||||
{ did: 'did:ethr:test', contactMethods: 'invalid' as any },
|
||||
{ did: 'did:ethr:test', contactMethods: [null] as any },
|
||||
{ did: 'did:ethr:test', contactMethods: [{ invalid: 'data' }] as any }
|
||||
]
|
||||
{ did: "" },
|
||||
{ did: "invalid-did" },
|
||||
{ did: "did:ethr:test", name: null as any },
|
||||
{ did: "did:ethr:test", contactMethods: "invalid" as any },
|
||||
{ did: "did:ethr:test", contactMethods: [null] as any },
|
||||
{ did: "did:ethr:test", contactMethods: [{ invalid: "data" }] as any },
|
||||
];
|
||||
|
||||
/**
|
||||
* Create contact with specific characteristics for testing
|
||||
*/
|
||||
export const createContactWithMethods = (methods: ContactMethod[]): Contact =>
|
||||
createStandardMockContact({ contactMethods: methods })
|
||||
export const createContactWithMethods = (methods: ContactMethod[]): Contact =>
|
||||
createStandardMockContact({ contactMethods: methods });
|
||||
|
||||
export const createContactWithNotes = (notes: string): Contact =>
|
||||
createStandardMockContact({ notes })
|
||||
export const createContactWithNotes = (notes: string): Contact =>
|
||||
createStandardMockContact({ notes });
|
||||
|
||||
export const createContactWithName = (name: string): Contact =>
|
||||
createStandardMockContact({ name })
|
||||
export const createContactWithName = (name: string): Contact =>
|
||||
createStandardMockContact({ name });
|
||||
|
||||
export const createContactWithDid = (did: string): Contact =>
|
||||
createStandardMockContact({ did })
|
||||
export const createContactWithDid = (did: string): Contact =>
|
||||
createStandardMockContact({ did });
|
||||
|
||||
export const createRegisteredContact = (): Contact =>
|
||||
createStandardMockContact({ registered: true })
|
||||
export const createRegisteredContact = (): Contact =>
|
||||
createStandardMockContact({ registered: true });
|
||||
|
||||
export const createUnregisteredContact = (): Contact =>
|
||||
createStandardMockContact({ registered: false })
|
||||
export const createUnregisteredContact = (): Contact =>
|
||||
createStandardMockContact({ registered: false });
|
||||
|
||||
export const createContactThatSeesMe = (): Contact =>
|
||||
createStandardMockContact({ seesMe: true })
|
||||
export const createContactThatSeesMe = (): Contact =>
|
||||
createStandardMockContact({ seesMe: true });
|
||||
|
||||
export const createContactThatDoesntSeeMe = (): Contact =>
|
||||
createStandardMockContact({ seesMe: false })
|
||||
export const createContactThatDoesntSeeMe = (): Contact =>
|
||||
createStandardMockContact({ seesMe: false });
|
||||
|
||||
/**
|
||||
* Create mock project data for testing
|
||||
@@ -125,12 +124,12 @@ export const createContactThatDoesntSeeMe = (): Contact =>
|
||||
export const createMockProject = (overrides = {}) => ({
|
||||
id: `project-${Date.now()}`,
|
||||
name: `Test Project ${Date.now()}`,
|
||||
description: 'Test project description',
|
||||
status: 'active',
|
||||
description: "Test project description",
|
||||
status: "active",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create mock account data for testing
|
||||
@@ -138,26 +137,26 @@ export const createMockProject = (overrides = {}) => ({
|
||||
export const createMockAccount = (overrides = {}) => ({
|
||||
id: `account-${Date.now()}`,
|
||||
name: `Test Account ${Date.now()}`,
|
||||
email: 'test@example.com',
|
||||
balance: 100.00,
|
||||
currency: 'USD',
|
||||
email: "test@example.com",
|
||||
balance: 100.0,
|
||||
currency: "USD",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create mock transaction data for testing
|
||||
*/
|
||||
export const createMockTransaction = (overrides = {}) => ({
|
||||
id: `transaction-${Date.now()}`,
|
||||
amount: 50.00,
|
||||
type: 'credit',
|
||||
description: 'Test transaction',
|
||||
status: 'completed',
|
||||
amount: 50.0,
|
||||
type: "credit",
|
||||
description: "Test transaction",
|
||||
status: "completed",
|
||||
createdAt: new Date(),
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create mock user data for testing
|
||||
@@ -165,53 +164,53 @@ export const createMockTransaction = (overrides = {}) => ({
|
||||
export const createMockUser = (overrides = {}) => ({
|
||||
id: `user-${Date.now()}`,
|
||||
username: `testuser${Date.now()}`,
|
||||
email: 'test@example.com',
|
||||
firstName: 'Test',
|
||||
lastName: 'User',
|
||||
email: "test@example.com",
|
||||
firstName: "Test",
|
||||
lastName: "User",
|
||||
isActive: true,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create mock settings data for testing
|
||||
*/
|
||||
export const createMockSettings = (overrides = {}) => ({
|
||||
theme: 'light',
|
||||
language: 'en',
|
||||
theme: "light",
|
||||
language: "en",
|
||||
notifications: true,
|
||||
autoSave: true,
|
||||
privacy: {
|
||||
profileVisibility: 'public',
|
||||
dataSharing: false
|
||||
profileVisibility: "public",
|
||||
dataSharing: false,
|
||||
},
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create mock notification data for testing
|
||||
*/
|
||||
export const createMockNotification = (overrides = {}) => ({
|
||||
id: `notification-${Date.now()}`,
|
||||
type: 'info',
|
||||
title: 'Test Notification',
|
||||
message: 'This is a test notification',
|
||||
type: "info",
|
||||
title: "Test Notification",
|
||||
message: "This is a test notification",
|
||||
isRead: false,
|
||||
createdAt: new Date(),
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create mock error data for testing
|
||||
*/
|
||||
export const createMockError = (overrides = {}) => ({
|
||||
code: 'TEST_ERROR',
|
||||
message: 'Test error message',
|
||||
details: 'Test error details',
|
||||
code: "TEST_ERROR",
|
||||
message: "Test error message",
|
||||
details: "Test error details",
|
||||
timestamp: new Date(),
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create mock API response data for testing
|
||||
@@ -219,10 +218,10 @@ export const createMockError = (overrides = {}) => ({
|
||||
export const createMockApiResponse = (overrides = {}) => ({
|
||||
success: true,
|
||||
data: {},
|
||||
message: 'Success',
|
||||
message: "Success",
|
||||
timestamp: new Date(),
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
/**
|
||||
* Create mock pagination data for testing
|
||||
@@ -234,5 +233,5 @@ export const createMockPagination = (overrides = {}) => ({
|
||||
totalPages: 10,
|
||||
hasNext: true,
|
||||
hasPrev: false,
|
||||
...overrides
|
||||
})
|
||||
...overrides,
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { config } from '@vue/test-utils'
|
||||
import { vi } from 'vitest'
|
||||
import { config } from "@vue/test-utils";
|
||||
import { vi } from "vitest";
|
||||
|
||||
/**
|
||||
* Test Setup Configuration for TimeSafari
|
||||
*
|
||||
*
|
||||
* Configures the testing environment for Vue components with proper mocking
|
||||
* and global test utilities. Sets up JSDOM environment for component testing.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
|
||||
@@ -15,19 +15,19 @@ global.ResizeObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}))
|
||||
}));
|
||||
|
||||
// Mock IntersectionObserver
|
||||
global.IntersectionObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}))
|
||||
}));
|
||||
|
||||
// Mock matchMedia
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
Object.defineProperty(window, "matchMedia", {
|
||||
writable: true,
|
||||
value: vi.fn().mockImplementation(query => ({
|
||||
value: vi.fn().mockImplementation((query) => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
@@ -37,7 +37,7 @@ Object.defineProperty(window, 'matchMedia', {
|
||||
removeEventListener: vi.fn(),
|
||||
dispatchEvent: vi.fn(),
|
||||
})),
|
||||
})
|
||||
});
|
||||
|
||||
// Mock localStorage
|
||||
const localStorageMock = {
|
||||
@@ -45,8 +45,8 @@ const localStorageMock = {
|
||||
setItem: vi.fn(),
|
||||
removeItem: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
}
|
||||
global.localStorage = localStorageMock
|
||||
};
|
||||
global.localStorage = localStorageMock;
|
||||
|
||||
// Mock sessionStorage
|
||||
const sessionStorageMock = {
|
||||
@@ -54,22 +54,22 @@ const sessionStorageMock = {
|
||||
setItem: vi.fn(),
|
||||
removeItem: vi.fn(),
|
||||
clear: vi.fn(),
|
||||
}
|
||||
global.sessionStorage = sessionStorageMock
|
||||
};
|
||||
global.sessionStorage = sessionStorageMock;
|
||||
|
||||
// Configure Vue Test Utils
|
||||
config.global.stubs = {
|
||||
// Add any global component stubs here
|
||||
}
|
||||
};
|
||||
|
||||
// Mock console methods to reduce noise in tests
|
||||
const originalConsole = { ...console }
|
||||
const originalConsole = { ...console };
|
||||
beforeEach(() => {
|
||||
console.warn = vi.fn()
|
||||
console.error = vi.fn()
|
||||
})
|
||||
console.warn = vi.fn();
|
||||
console.error = vi.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
console.warn = originalConsole.warn
|
||||
console.error = originalConsole.error
|
||||
})
|
||||
console.warn = originalConsole.warn;
|
||||
console.error = originalConsole.error;
|
||||
});
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/**
|
||||
* Component Test Utilities
|
||||
*
|
||||
*
|
||||
* Centralized utilities for component testing across the application.
|
||||
* Provides consistent patterns for mounting, testing, and validating components.
|
||||
*
|
||||
*
|
||||
* @author Matthew Raymer
|
||||
*/
|
||||
|
||||
import { mount, VueWrapper } from '@vue/test-utils'
|
||||
import { Component } from 'vue'
|
||||
import { mount, VueWrapper } from "@vue/test-utils";
|
||||
import { Component } from "vue";
|
||||
|
||||
/**
|
||||
* Create a component wrapper factory with consistent configuration
|
||||
*
|
||||
*
|
||||
* @param Component - Vue component to test
|
||||
* @param defaultProps - Default props for the component
|
||||
* @param globalOptions - Global options for mounting
|
||||
@@ -21,7 +21,7 @@ import { Component } from 'vue'
|
||||
export const createComponentWrapper = (
|
||||
Component: Component,
|
||||
defaultProps = {},
|
||||
globalOptions = {}
|
||||
globalOptions = {},
|
||||
) => {
|
||||
return (props = {}, additionalGlobalOptions = {}) => {
|
||||
return mount(Component, {
|
||||
@@ -31,243 +31,244 @@ export const createComponentWrapper = (
|
||||
// Common stubs for external components
|
||||
EntityIcon: {
|
||||
template: '<div class="entity-icon-stub">EntityIcon</div>',
|
||||
props: ['contact', 'iconSize']
|
||||
props: ["contact", "iconSize"],
|
||||
},
|
||||
// Add more common stubs as needed
|
||||
},
|
||||
...globalOptions,
|
||||
...additionalGlobalOptions
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
...additionalGlobalOptions,
|
||||
},
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a test data factory with consistent patterns
|
||||
*
|
||||
*
|
||||
* @param baseData - Base data object
|
||||
* @returns Function that creates test data with overrides
|
||||
*/
|
||||
export const createTestDataFactory = <T>(baseData: T) => {
|
||||
return (overrides: Partial<T> = {}) => ({
|
||||
...baseData,
|
||||
...overrides
|
||||
})
|
||||
}
|
||||
...overrides,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Wait for async operations to complete
|
||||
*
|
||||
*
|
||||
* @param wrapper - Vue wrapper instance
|
||||
* @param timeout - Timeout in milliseconds
|
||||
*/
|
||||
export const waitForAsync = async (wrapper: VueWrapper, timeout = 100) => {
|
||||
await wrapper.vm.$nextTick()
|
||||
await new Promise(resolve => setTimeout(resolve, timeout))
|
||||
}
|
||||
await wrapper.vm.$nextTick();
|
||||
await new Promise((resolve) => setTimeout(resolve, timeout));
|
||||
};
|
||||
|
||||
/**
|
||||
* Test component lifecycle events
|
||||
*
|
||||
*
|
||||
* @param wrapper - Vue wrapper instance
|
||||
* @param lifecycleEvents - Array of lifecycle events to test
|
||||
*/
|
||||
export const testLifecycleEvents = async (
|
||||
wrapper: VueWrapper,
|
||||
lifecycleEvents: string[] = ['mounted', 'updated', 'unmounted']
|
||||
lifecycleEvents: string[] = ["mounted", "updated", "unmounted"],
|
||||
) => {
|
||||
const results = []
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const event of lifecycleEvents) {
|
||||
try {
|
||||
// Simulate lifecycle event
|
||||
if (event === 'mounted') {
|
||||
if (event === "mounted") {
|
||||
// Component is already mounted
|
||||
results.push({ event, success: true })
|
||||
} else if (event === 'updated') {
|
||||
await wrapper.vm.$forceUpdate()
|
||||
results.push({ event, success: true })
|
||||
} else if (event === 'unmounted') {
|
||||
await wrapper.unmount()
|
||||
results.push({ event, success: true })
|
||||
results.push({ event, success: true });
|
||||
} else if (event === "updated") {
|
||||
await wrapper.vm.$forceUpdate();
|
||||
results.push({ event, success: true });
|
||||
} else if (event === "unmounted") {
|
||||
await wrapper.unmount();
|
||||
results.push({ event, success: true });
|
||||
}
|
||||
} catch (error) {
|
||||
results.push({ event, success: false, error })
|
||||
results.push({ event, success: false, error });
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test computed properties
|
||||
*
|
||||
*
|
||||
* @param wrapper - Vue wrapper instance
|
||||
* @param computedProps - Array of computed property names to test
|
||||
*/
|
||||
export const testComputedProperties = (
|
||||
wrapper: VueWrapper,
|
||||
computedProps: string[]
|
||||
computedProps: string[],
|
||||
) => {
|
||||
const results = []
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const propName of computedProps) {
|
||||
try {
|
||||
const value = (wrapper.vm as any)[propName]
|
||||
results.push({ propName, success: true, value })
|
||||
const value = (wrapper.vm as any)[propName];
|
||||
results.push({ propName, success: true, value });
|
||||
} catch (error) {
|
||||
results.push({ propName, success: false, error })
|
||||
results.push({ propName, success: false, error });
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test component watchers
|
||||
*
|
||||
*
|
||||
* @param wrapper - Vue wrapper instance
|
||||
* @param watcherTests - Array of watcher test configurations
|
||||
*/
|
||||
export const testWatchers = async (
|
||||
wrapper: VueWrapper,
|
||||
watcherTests: Array<{
|
||||
property: string
|
||||
newValue: any
|
||||
expectedEmit?: string
|
||||
}>
|
||||
property: string;
|
||||
newValue: any;
|
||||
expectedEmit?: string;
|
||||
}>,
|
||||
) => {
|
||||
const results = []
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const test of watcherTests) {
|
||||
try {
|
||||
const initialEmitCount = wrapper.emitted() ? Object.keys(wrapper.emitted()).length : 0
|
||||
|
||||
const initialEmitCount = wrapper.emitted()
|
||||
? Object.keys(wrapper.emitted()).length
|
||||
: 0;
|
||||
|
||||
// Trigger watcher by changing property
|
||||
await wrapper.setProps({ [test.property]: test.newValue })
|
||||
await wrapper.vm.$nextTick()
|
||||
|
||||
const finalEmitCount = wrapper.emitted() ? Object.keys(wrapper.emitted()).length : 0
|
||||
const emitCount = finalEmitCount - initialEmitCount
|
||||
|
||||
await wrapper.setProps({ [test.property]: test.newValue });
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
const finalEmitCount = wrapper.emitted()
|
||||
? Object.keys(wrapper.emitted()).length
|
||||
: 0;
|
||||
const emitCount = finalEmitCount - initialEmitCount;
|
||||
|
||||
results.push({
|
||||
property: test.property,
|
||||
success: true,
|
||||
emitCount,
|
||||
expectedEmit: test.expectedEmit
|
||||
})
|
||||
expectedEmit: test.expectedEmit,
|
||||
});
|
||||
} catch (error) {
|
||||
results.push({
|
||||
property: test.property,
|
||||
success: false,
|
||||
error
|
||||
})
|
||||
error,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test component performance
|
||||
*
|
||||
*
|
||||
* @param testFunction - Function to test
|
||||
* @param threshold - Performance threshold in milliseconds
|
||||
*/
|
||||
export const testPerformance = (
|
||||
testFunction: () => void,
|
||||
threshold = 100
|
||||
) => {
|
||||
const start = performance.now()
|
||||
testFunction()
|
||||
const end = performance.now()
|
||||
|
||||
const duration = end - start
|
||||
const passed = duration < threshold
|
||||
|
||||
export const testPerformance = (testFunction: () => void, threshold = 100) => {
|
||||
const start = performance.now();
|
||||
testFunction();
|
||||
const end = performance.now();
|
||||
|
||||
const duration = end - start;
|
||||
const passed = duration < threshold;
|
||||
|
||||
return {
|
||||
duration,
|
||||
threshold,
|
||||
passed,
|
||||
performance: `${duration.toFixed(2)}ms`
|
||||
}
|
||||
}
|
||||
performance: `${duration.toFixed(2)}ms`,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Test accessibility features
|
||||
*
|
||||
*
|
||||
* @param wrapper - Vue wrapper instance
|
||||
* @param accessibilityChecks - Array of accessibility checks to perform
|
||||
*/
|
||||
export const testAccessibility = (
|
||||
wrapper: VueWrapper,
|
||||
_wrapper: VueWrapper,
|
||||
accessibilityChecks: Array<{
|
||||
name: string
|
||||
test: (wrapper: VueWrapper) => boolean
|
||||
}>
|
||||
name: string;
|
||||
test: (_wrapper: VueWrapper) => boolean;
|
||||
}>,
|
||||
) => {
|
||||
const results = []
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const check of accessibilityChecks) {
|
||||
try {
|
||||
const passed = check.test(wrapper)
|
||||
results.push({ name: check.name, success: true, passed })
|
||||
const passed = check.test(_wrapper);
|
||||
results.push({ name: check.name, success: true, passed });
|
||||
} catch (error) {
|
||||
results.push({ name: check.name, success: false, error })
|
||||
results.push({ name: check.name, success: false, error });
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create mock event listeners
|
||||
*
|
||||
*
|
||||
* @param events - Array of event names to mock
|
||||
*/
|
||||
export const createMockEventListeners = (events: string[]) => {
|
||||
const listeners: Record<string, jest.Mock> = {}
|
||||
|
||||
events.forEach(event => {
|
||||
listeners[event] = jest.fn()
|
||||
})
|
||||
|
||||
return listeners
|
||||
}
|
||||
const listeners: Record<string, jest.Mock> = {};
|
||||
|
||||
events.forEach((event) => {
|
||||
listeners[event] = jest.fn();
|
||||
});
|
||||
|
||||
return listeners;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test component error handling
|
||||
*
|
||||
*
|
||||
* @param wrapper - Vue wrapper instance
|
||||
* @param errorScenarios - Array of error scenarios to test
|
||||
*/
|
||||
export const testErrorHandling = async (
|
||||
wrapper: VueWrapper,
|
||||
_wrapper: VueWrapper,
|
||||
errorScenarios: Array<{
|
||||
name: string
|
||||
action: (wrapper: VueWrapper) => Promise<void>
|
||||
expectedBehavior: string
|
||||
}>
|
||||
name: string;
|
||||
action: (_wrapper: VueWrapper) => Promise<void>;
|
||||
expectedBehavior: string;
|
||||
}>,
|
||||
) => {
|
||||
const results = []
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const scenario of errorScenarios) {
|
||||
try {
|
||||
await scenario.action(wrapper)
|
||||
await scenario.action(_wrapper);
|
||||
results.push({
|
||||
name: scenario.name,
|
||||
success: true,
|
||||
expectedBehavior: scenario.expectedBehavior
|
||||
})
|
||||
expectedBehavior: scenario.expectedBehavior,
|
||||
});
|
||||
} catch (error) {
|
||||
results.push({
|
||||
name: scenario.name,
|
||||
success: false,
|
||||
error,
|
||||
expectedBehavior: scenario.expectedBehavior
|
||||
})
|
||||
expectedBehavior: scenario.expectedBehavior,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -220,13 +220,20 @@ export const PlatformServiceMixin = {
|
||||
const obj: Record<string, unknown> = {};
|
||||
columns.forEach((column, index) => {
|
||||
let value = row[index];
|
||||
|
||||
|
||||
// Convert SQLite integer booleans to JavaScript booleans
|
||||
if (column === 'isRegistered' || column === 'finishedOnboarding' ||
|
||||
column === 'filterFeedByVisible' || column === 'filterFeedByNearby' ||
|
||||
column === 'hideRegisterPromptOnNewContact' || column === 'showContactGivesInline' ||
|
||||
column === 'showGeneralAdvanced' || column === 'showShortcutBvc' ||
|
||||
column === 'warnIfProdServer' || column === 'warnIfTestServer') {
|
||||
if (
|
||||
column === "isRegistered" ||
|
||||
column === "finishedOnboarding" ||
|
||||
column === "filterFeedByVisible" ||
|
||||
column === "filterFeedByNearby" ||
|
||||
column === "hideRegisterPromptOnNewContact" ||
|
||||
column === "showContactGivesInline" ||
|
||||
column === "showGeneralAdvanced" ||
|
||||
column === "showShortcutBvc" ||
|
||||
column === "warnIfProdServer" ||
|
||||
column === "warnIfTestServer"
|
||||
) {
|
||||
if (value === 1) {
|
||||
value = true;
|
||||
} else if (value === 0) {
|
||||
@@ -234,7 +241,7 @@ export const PlatformServiceMixin = {
|
||||
}
|
||||
// Keep null values as null
|
||||
}
|
||||
|
||||
|
||||
obj[column] = value;
|
||||
});
|
||||
return obj;
|
||||
@@ -1401,7 +1408,9 @@ export const PlatformServiceMixin = {
|
||||
);
|
||||
|
||||
if (!result?.values?.length) {
|
||||
logger.warn(`[PlatformServiceMixin] No settings found for DID: ${did}`);
|
||||
logger.warn(
|
||||
`[PlatformServiceMixin] No settings found for DID: ${did}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1411,7 +1420,9 @@ export const PlatformServiceMixin = {
|
||||
);
|
||||
|
||||
if (!mappedResults.length) {
|
||||
logger.warn(`[PlatformServiceMixin] Failed to map settings for DID: ${did}`);
|
||||
logger.warn(
|
||||
`[PlatformServiceMixin] Failed to map settings for DID: ${did}`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1426,7 +1437,10 @@ export const PlatformServiceMixin = {
|
||||
|
||||
return settings;
|
||||
} catch (error) {
|
||||
logger.error(`[PlatformServiceMixin] Error debugging settings for DID ${did}:`, error);
|
||||
logger.error(
|
||||
`[PlatformServiceMixin] Error debugging settings for DID ${did}:`,
|
||||
error,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
@@ -1440,14 +1454,24 @@ export const PlatformServiceMixin = {
|
||||
async $debugMergedSettings(did: string): Promise<void> {
|
||||
try {
|
||||
// Get default settings
|
||||
const defaultSettings = await this.$getSettings(MASTER_SETTINGS_KEY, {});
|
||||
logger.info(`[PlatformServiceMixin] Default settings:`, defaultSettings);
|
||||
const defaultSettings = await this.$getSettings(
|
||||
MASTER_SETTINGS_KEY,
|
||||
{},
|
||||
);
|
||||
logger.info(
|
||||
`[PlatformServiceMixin] Default settings:`,
|
||||
defaultSettings,
|
||||
);
|
||||
|
||||
// Get DID-specific settings
|
||||
const didSettings = await this.$debugDidSettings(did);
|
||||
|
||||
// Get merged settings
|
||||
const mergedSettings = await this.$getMergedSettings(MASTER_SETTINGS_KEY, did, defaultSettings || {});
|
||||
const mergedSettings = await this.$getMergedSettings(
|
||||
MASTER_SETTINGS_KEY,
|
||||
did,
|
||||
defaultSettings || {},
|
||||
);
|
||||
|
||||
logger.info(`[PlatformServiceMixin] Merged settings for ${did}:`, {
|
||||
defaultSettings,
|
||||
@@ -1456,7 +1480,10 @@ export const PlatformServiceMixin = {
|
||||
isRegistered: mergedSettings.isRegistered,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(`[PlatformServiceMixin] Error debugging merged settings for DID ${did}:`, error);
|
||||
logger.error(
|
||||
`[PlatformServiceMixin] Error debugging merged settings for DID ${did}:`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1423,7 +1423,8 @@ export default class AccountViewView extends Vue {
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
this.limitsMessage = ACCOUNT_VIEW_CONSTANTS.LIMITS.ERROR_RETRIEVING_LIMITS;
|
||||
this.limitsMessage =
|
||||
ACCOUNT_VIEW_CONSTANTS.LIMITS.ERROR_RETRIEVING_LIMITS;
|
||||
console.log("error: ", error);
|
||||
// this.notify.error(this.limitsMessage, TIMEOUTS.STANDARD);
|
||||
} finally {
|
||||
@@ -1483,7 +1484,7 @@ export default class AccountViewView extends Vue {
|
||||
async deleteImage(): Promise<void> {
|
||||
try {
|
||||
// Extract the image ID from the full URL
|
||||
const imageId = this.profileImageUrl?.split('/').pop();
|
||||
const imageId = this.profileImageUrl?.split("/").pop();
|
||||
if (!imageId) {
|
||||
this.notify.error("Invalid image URL");
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user