diff --git a/web/site/app/components/Sbc/Docs/SideNavigation.vue b/web/site/app/components/Sbc/Docs/SideNavigation.vue
index e2a40a8f..939e3560 100644
--- a/web/site/app/components/Sbc/Docs/SideNavigation.vue
+++ b/web/site/app/components/Sbc/Docs/SideNavigation.vue
@@ -4,7 +4,7 @@ defineProps<{
}>()
-
diff --git a/web/site/app/composables/docPageData.ts b/web/site/app/composables/docPageData.ts
index d5a95d5b..d4fe6483 100644
--- a/web/site/app/composables/docPageData.ts
+++ b/web/site/app/composables/docPageData.ts
@@ -40,16 +40,12 @@ export function useDocPageData () {
// update data when locale or route changes
watch([locale, routeWithoutLocale], async () => {
await initDocPageData()
- })
+ }, { immediate: true })
// return current page data table of contents
const tocLinks = computed
(() => docPageData.value?.body?.toc?.links ?? [])
const currentDir = computed(() => docPageData.value?._path)
- onMounted(() => {
- initDocPageData()
- })
-
- return { docPageData, tocLinks, currentDir, createPageHead }
+ return { docPageData, tocLinks, currentDir, createPageHead, initDocPageData }
}
diff --git a/web/site/app/tests/e2e/login-flow.test.ts b/web/site/app/tests/e2e/journeys/login-flow.test.ts
similarity index 82%
rename from web/site/app/tests/e2e/login-flow.test.ts
rename to web/site/app/tests/e2e/journeys/login-flow.test.ts
index 7be32fd4..8c4b3f51 100644
--- a/web/site/app/tests/e2e/login-flow.test.ts
+++ b/web/site/app/tests/e2e/journeys/login-flow.test.ts
@@ -1,6 +1,6 @@
import { test } from '@playwright/test'
-test('test', async ({ page }) => {
+test.skip('test', async ({ page }) => {
await page.goto('http://localhost:3467/en-CA')
await page.getByRole('link', { name: 'Dashboard' }).click()
const page1Promise = page.waitForEvent('popup')
@@ -9,9 +9,9 @@ test('test', async ({ page }) => {
await page1.getByLabel('Log in with Test with').click()
await page1.getByLabel('Email or username').click()
await page1.getByLabel('Email or username').press('CapsLock')
- await page1.getByLabel('Email or username').fill('BCREG4000')
+ await page1.getByLabel('Email or username').fill('') // username
await page1.getByLabel('Password').click()
- await page1.getByLabel('Password').fill('98940000')
+ await page1.getByLabel('Password').fill('') // password
await page1.getByLabel('Password').press('Tab')
await page1.getByRole('button', { name: 'Continue' }).click()
await page.goto('http://localhost:3467/en-CA')
diff --git a/web/site/app/tests/e2e/all-products-page.test.ts b/web/site/app/tests/e2e/pages/all-products-page.test.ts
similarity index 77%
rename from web/site/app/tests/e2e/all-products-page.test.ts
rename to web/site/app/tests/e2e/pages/all-products-page.test.ts
index 14b2d77a..540832ee 100644
--- a/web/site/app/tests/e2e/all-products-page.test.ts
+++ b/web/site/app/tests/e2e/pages/all-products-page.test.ts
@@ -6,22 +6,17 @@ test.describe('products page', () => {
await page.goto('/en-CA/products')
})
- test('page contents', async ({ page }) => {
- const h1 = await page.textContent('h1')
- expect(h1).toBe('All Products')
- await expect(page.getByTestId('product-card')).toHaveCount(7) // there should be 7 product cards
- })
-
- test('accessibility', async ({ page }) => {
- await page
- .getByText('All Products')
- .first()
- .click() // wait for page load before runnign a11y checks? fails without this
-
+ test.afterEach(async ({ page }) => {
const a11yResults = await new AxeBuilder({ page })
.exclude('#locale-select-dropdown') // headless ui dropdown fails the axe check
.analyze()
expect(a11yResults.violations).toEqual([])
})
+
+ test('page contents', async ({ page }) => {
+ const h1 = await page.textContent('h1')
+ expect(h1).toBe('All Products')
+ await expect(page.getByTestId('product-card')).toHaveCount(7) // there should be 7 product cards
+ })
})
diff --git a/web/site/app/tests/e2e/dashboard-page.test.ts b/web/site/app/tests/e2e/pages/dashboard-page.test.ts
similarity index 94%
rename from web/site/app/tests/e2e/dashboard-page.test.ts
rename to web/site/app/tests/e2e/pages/dashboard-page.test.ts
index d1bebb9e..1300cf95 100644
--- a/web/site/app/tests/e2e/dashboard-page.test.ts
+++ b/web/site/app/tests/e2e/pages/dashboard-page.test.ts
@@ -1,7 +1,7 @@
import { test, expect } from '@playwright/test'
import AxeBuilder from '@axe-core/playwright'
-test.describe('dashboard page', () => {
+test.describe.skip('dashboard page', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/en-CA/sbc/dashboard')
})
diff --git a/web/site/app/tests/e2e/docs-page.test.ts b/web/site/app/tests/e2e/pages/docs-page.test.ts
similarity index 74%
rename from web/site/app/tests/e2e/docs-page.test.ts
rename to web/site/app/tests/e2e/pages/docs-page.test.ts
index 25d9253e..517d3b8f 100644
--- a/web/site/app/tests/e2e/docs-page.test.ts
+++ b/web/site/app/tests/e2e/pages/docs-page.test.ts
@@ -6,21 +6,17 @@ test.describe('docs page', () => {
await page.goto('/en-CA/products/get-started')
})
- test('page contents', async ({ page }) => {
- const h1 = await page.textContent('h1')
- expect(h1).toBe('Account Setup')
- })
-
- test('accessibility', async ({ page }) => {
- await page
- .getByText('Account Setup')
- .first()
- .click() // wait for page load before runnign a11y checks? fails without this
-
+ test.afterEach(async ({ page }) => {
const a11yResults = await new AxeBuilder({ page })
.exclude('#locale-select-dropdown') // headless ui dropdown fails the axe check
.analyze()
expect(a11yResults.violations).toEqual([])
})
+
+ test('page contents', async ({ page }) => {
+ const h1 = await page.textContent('h1')
+ expect(h1).toBe('Account Setup')
+ expect(page.getByTestId('docs-side-navigation')).toBeDefined()
+ })
})
diff --git a/web/site/app/tests/e2e/home-page.test.ts b/web/site/app/tests/e2e/pages/home-page.test.ts
similarity index 94%
rename from web/site/app/tests/e2e/home-page.test.ts
rename to web/site/app/tests/e2e/pages/home-page.test.ts
index 962e8417..02257d9f 100644
--- a/web/site/app/tests/e2e/home-page.test.ts
+++ b/web/site/app/tests/e2e/pages/home-page.test.ts
@@ -6,6 +6,14 @@ test.describe('home page', () => {
await page.goto('/en-CA')
})
+ test.afterEach(async ({ page }) => {
+ const a11yResults = await new AxeBuilder({ page })
+ .exclude('#locale-select-dropdown') // headless ui dropdown fails the axe check
+ .analyze()
+
+ expect(a11yResults.violations).toEqual([])
+ })
+
test('page contents', async ({ page }) => {
const h1 = await page.textContent('h1')
const p = await page.textContent('p')
@@ -14,12 +22,4 @@ test.describe('home page', () => {
expect(h1).toBe('BC Registries API Gateway')
expect(p).toBe('Welcome to the BC Registries API Gateway! Access API information for all BC Registries services here.')
})
-
- test('accessibility', async ({ page }) => {
- const a11yResults = await new AxeBuilder({ page })
- .exclude('#locale-select-dropdown') // headless ui dropdown fails the axe check
- .analyze()
-
- expect(a11yResults.violations).toEqual([])
- })
})
diff --git a/web/site/app/tests/e2e/tos-page.test.ts b/web/site/app/tests/e2e/pages/tos-page.test.ts
similarity index 93%
rename from web/site/app/tests/e2e/tos-page.test.ts
rename to web/site/app/tests/e2e/pages/tos-page.test.ts
index 1d7dfdbb..a75de72c 100644
--- a/web/site/app/tests/e2e/tos-page.test.ts
+++ b/web/site/app/tests/e2e/pages/tos-page.test.ts
@@ -1,7 +1,7 @@
import { test, expect } from '@playwright/test'
import AxeBuilder from '@axe-core/playwright'
-test.describe('terms of use page', () => {
+test.describe.skip('terms of use page', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/en-CA/sbc/tos')
})
diff --git a/web/site/app/tests/setup/i18n.ts b/web/site/app/tests/setup/i18n.ts
index bc6f00d4..4369d484 100644
--- a/web/site/app/tests/setup/i18n.ts
+++ b/web/site/app/tests/setup/i18n.ts
@@ -1,6 +1,6 @@
import { config } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'
-import en from '~/app/locales/en-CA'
+import en from '~~/app/locales/en-CA'
export const mockedI18n = createI18n({
locale: 'en-CA',
diff --git a/web/site/app/tests/unit/components/SbcDocsProductCard.test.ts b/web/site/app/tests/unit/components/SbcDocsProductCard.test.ts
new file mode 100644
index 00000000..f2aa3e6f
--- /dev/null
+++ b/web/site/app/tests/unit/components/SbcDocsProductCard.test.ts
@@ -0,0 +1,45 @@
+import { describe, it, expect, vi } from 'vitest'
+import { mockNuxtImport, mountSuspended } from '@nuxt/test-utils/runtime'
+import { SbcDocsProductCard } from '#components'
+import { enI18n } from '~/tests/mocks/i18n'
+
+const { navigateToMock } = vi.hoisted(() => ({ navigateToMock: vi.fn() }))
+mockNuxtImport('navigateTo', () => navigateToMock)
+
+describe('SbcDocsProductCard', () => {
+ const props = {
+ name: 'Test Product',
+ description: 'This is a test product',
+ badge: 'New',
+ bulletPoints: ['Feature 1', 'Feature 2'],
+ directory: 'test-product'
+ }
+
+ it('renders', async () => {
+ const wrapper = await mountSuspended(SbcDocsProductCard, {
+ props,
+ global: {
+ plugins: [enI18n]
+ }
+ })
+
+ expect(wrapper.find('[data-testid="product-card"]').exists()).toBe(true)
+ expect(wrapper.text()).toContain(props.name)
+ expect(wrapper.text()).toContain(props.description)
+ expect(wrapper.text()).toContain(props.badge)
+ expect(wrapper.text()).toContain(props.bulletPoints[0])
+ expect(wrapper.text()).toContain(props.bulletPoints[1])
+ })
+
+ it('navigates when clicked', async () => {
+ const wrapper = await mountSuspended(SbcDocsProductCard, {
+ props,
+ global: {
+ plugins: [enI18n]
+ }
+ })
+
+ await wrapper.trigger('click')
+ expect(navigateTo).toHaveBeenCalledWith('/en-CA/products/test-product/overview')
+ })
+})
diff --git a/web/site/app/tests/unit/components/SbcDocsTableOfContents.test.ts b/web/site/app/tests/unit/components/SbcDocsTableOfContents.test.ts
new file mode 100644
index 00000000..8fca3920
--- /dev/null
+++ b/web/site/app/tests/unit/components/SbcDocsTableOfContents.test.ts
@@ -0,0 +1,37 @@
+import { describe, it, expect } from 'vitest'
+import { mountSuspended } from '@nuxt/test-utils/runtime'
+import { SbcDocsTableOfContents } from '#components'
+
+describe('TableOfContents', () => {
+ const props = {
+ tocLinks: [
+ { id: 'section-1', text: 'Section 1', children: [], depth: 1 },
+ { id: 'section-2', text: 'Section 2', children: [{ id: 'section-2-1', text: 'Section 2.1', depth: 2 }], depth: 1 }
+ ],
+ currentDir: '/docs',
+ activeTocId: 'section-1',
+ hideLabel: false
+ }
+
+ it('renders', async () => {
+ const wrapper = await mountSuspended(SbcDocsTableOfContents, {
+ props
+ })
+
+ expect(wrapper.find('nav[aria-label="table of contents"]').exists()).toBe(true)
+ expect(wrapper.text()).toContain('Table of Contents')
+ expect(wrapper.text()).toContain('Section 1')
+ expect(wrapper.text()).toContain('Section 2')
+ expect(wrapper.text()).toContain('Section 2.1')
+ })
+
+ it('highlights the active link', async () => {
+ const wrapper = await mountSuspended(SbcDocsTableOfContents, {
+ props
+ })
+
+ const activeLink = wrapper.find('.text-primary-500')
+ expect(activeLink.exists()).toBe(true)
+ expect(activeLink.text()).toBe('Section 1')
+ })
+})
diff --git a/web/site/app/tests/unit/composables/docPageData.test.ts b/web/site/app/tests/unit/composables/docPageData.test.ts
new file mode 100644
index 00000000..4d2289d2
--- /dev/null
+++ b/web/site/app/tests/unit/composables/docPageData.test.ts
@@ -0,0 +1,71 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest'
+import { mockNuxtImport } from '@nuxt/test-utils/runtime'
+import { useDocPageData } from '#imports'
+
+mockNuxtImport('useI18n', () => {
+ return () => {
+ return { locale: ref('en') }
+ }
+})
+
+mockNuxtImport('useRoute', () => {
+ return () => (
+ {
+ path: '/en-CA/products',
+ meta: {
+ layout: 'docs'
+ }
+ }
+ )
+})
+
+const queryContentMockData = {
+ _path: '/products/test',
+ _dir: 'get-started',
+ title: 'Test Title',
+ body: { toc: { links: [{ id: '1', text: 'Introduction', href: '#introduction' }] } }
+}
+
+const { queryContentMock } = vi.hoisted(() => ({
+ queryContentMock: vi.fn(() => ({
+ where: vi.fn().mockReturnThis(),
+ findOne: vi.fn(() => Promise.resolve(queryContentMockData))
+ }))
+}))
+mockNuxtImport('queryContent', () => queryContentMock)
+
+describe('useDocPageData', () => {
+ let composable: ReturnType
+
+ beforeEach(async () => {
+ composable = useDocPageData()
+ // wait for promises to resolve
+ await new Promise(resolve => setTimeout(resolve, 0))
+ })
+ it('should return correct values based off route', () => {
+ // assert doc page data
+ expect(composable.docPageData.value).toEqual(queryContentMockData)
+ // assert toc links
+ expect(composable.tocLinks.value).toEqual(queryContentMockData.body.toc.links)
+ // assert current dir
+ expect(composable.currentDir.value).toEqual(queryContentMockData._path)
+ // assert generated page head
+ expect(composable.createPageHead()).toBe('Get Started - Test Title')
+ })
+
+ // TODO: figure out how to test the watcher reacting to route changes
+ it.skip('should handle route changes', async () => {
+ const { docPageData, currentDir, tocLinks, createPageHead } = useDocPageData()
+ // wait for promises to resolve
+ await new Promise(resolve => setTimeout(resolve, 0))
+
+ // assert doc page data
+ expect(docPageData.value).toEqual(queryContentMockData)
+ // assert toc links
+ expect(tocLinks.value).toEqual(queryContentMockData.body.toc.links)
+ // assert current dir
+ expect(currentDir.value).toEqual(queryContentMockData._path)
+ // assert generated page head
+ expect(createPageHead()).toBe('Get Started - Test Title')
+ })
+})
diff --git a/web/site/app/tests/unit/composables/sbcNav.test.ts b/web/site/app/tests/unit/composables/sbcNav.test.ts
new file mode 100644
index 00000000..dac8e508
--- /dev/null
+++ b/web/site/app/tests/unit/composables/sbcNav.test.ts
@@ -0,0 +1,122 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest'
+import { mockNuxtImport } from '@nuxt/test-utils/runtime'
+import { useSbcNav } from '#imports'
+
+const localePathMock = vi.fn(path => `/en-CA${path}`)
+mockNuxtImport('useLocalePath', () => {
+ return () => localePathMock
+})
+
+mockNuxtImport('useI18n', () => {
+ return () => {
+ return {
+ locale: ref('en'),
+ t: (key: any) => key
+ }
+ }
+})
+
+const routeRef = ref({ path: '/en-CA/products' })
+mockNuxtImport('useRoute', () => {
+ return () => routeRef.value
+})
+
+mockNuxtImport('useRouter', () => {
+ return () => ({
+ isReady: vi.fn(() => Promise.resolve())
+ })
+})
+
+describe('useSbcNav', () => {
+ let composable: ReturnType
+
+ beforeEach(() => {
+ vi.clearAllMocks()
+ composable = useSbcNav()
+ })
+
+ it('should return main links', () => {
+ const { mainLinks } = composable
+
+ expect(mainLinks.value).toEqual([
+ {
+ icon: 'i-mdi-home',
+ label: 'btn.sbcConnect',
+ to: '/en-CA/'
+ },
+ {
+ icon: 'i-mdi-database',
+ label: 'btn.products',
+ to: '/en-CA/products'
+ },
+ {
+ icon: 'i-mdi-book-open-variant',
+ label: 'Docs',
+ to: '/en-CA/products/get-started/account-setup'
+ }
+ ])
+ })
+
+ it('should return loggedInUserOptions', () => {
+ const { loggedInUserOptions } = composable
+
+ expect(loggedInUserOptions.value).toEqual([
+ [
+ {
+ label: 'Account',
+ slot: 'account',
+ disabled: true
+ },
+ {
+ label: 'Log out',
+ icon: 'i-mdi-logout',
+ click: expect.any(Function)
+ }
+ ]
+ ])
+ })
+
+ it('should return loggedOutUserOptions', () => {
+ const { loggedOutUserOptions } = composable
+
+ expect(loggedOutUserOptions.value).toEqual([
+ [
+ {
+ label: 'Log in',
+ to: '/en-CA/sbc/auth/login',
+ icon: 'i-mdi-login'
+ },
+ {
+ label: 'Create Account',
+ icon: 'i-mdi-account-plus'
+ }
+ ]
+ ])
+ })
+
+ it('should open mobile nav', () => {
+ const { openMobileNav, mobileNavRef } = composable
+ expect(mobileNavRef.value).toBe(false)
+ openMobileNav()
+ expect(mobileNavRef.value).toBe(true)
+ })
+
+ it('should close mobile nav', async () => {
+ const { closeMobileNav, mobileNavRef } = composable
+
+ mobileNavRef.value = true
+ await closeMobileNav()
+ expect(mobileNavRef.value).toBe(false)
+ })
+
+ // TODO: figure out how to test the watcher reacting to route changes
+ it.skip('should close mobile nav on route change', async () => {
+ const { mobileNavRef } = composable
+ mobileNavRef.value = true
+ expect(mobileNavRef.value).toBe(true)
+ routeRef.value = { path: '/en-CA/new-path' }
+ await nextTick()
+
+ expect(mobileNavRef.value).toBe(false)
+ })
+})
diff --git a/web/site/app/utils/createContentNav.ts b/web/site/app/utils/createContentNav.ts
index 7df144df..c2fef91b 100644
--- a/web/site/app/utils/createContentNav.ts
+++ b/web/site/app/utils/createContentNav.ts
@@ -1,4 +1,4 @@
-import type { NavItem } from '@nuxt/content/dist/runtime/types'
+import type { NavItem } from '@nuxt/content'
import { handleContentDirectoryLabel } from './handleContentDirectoryLabel'
// maps nav items returned from fetchContentNavigation into usable array by UAccordian for navigation
diff --git a/web/site/content/en-CA/products/br/overview.md b/web/site/content/en-CA/products/br/overview.md
index 4e290c7a..83517e5b 100644
--- a/web/site/content/en-CA/products/br/overview.md
+++ b/web/site/content/en-CA/products/br/overview.md
@@ -74,7 +74,7 @@ All data with times are in UTC, both submitted and retrieved via the API. These
## Additional Resources
-- Refer to the BC Gov site to answer any business rule related questions including Fees
+- Refer to the BC Gov site to answer any business rule related questions including Fees
- Refer to the BC Registry site to open an account and see all the Registry services.
diff --git a/web/site/package.json b/web/site/package.json
index 458a63f0..15624857 100644
--- a/web/site/package.json
+++ b/web/site/package.json
@@ -2,7 +2,7 @@
"name": "sbc-apigw-site",
"private": true,
"type": "module",
- "version": "1.0.1",
+ "version": "1.0.2",
"scripts": {
"build-check": "nuxt build",
"build": "nuxt generate",
diff --git a/web/site/playwright.config.ts b/web/site/playwright.config.ts
index 2f5c0d8b..b09342d2 100644
--- a/web/site/playwright.config.ts
+++ b/web/site/playwright.config.ts
@@ -16,7 +16,7 @@ const devicesToTest = [
] satisfies Array
export default defineConfig({
- testDir: './tests/e2e',
+ testDir: './app/tests/e2e',
reporter: 'line',
// Fail the build on CI if you accidentally left test.only in the source code.
forbidOnly: !!process.env.CI,
diff --git a/web/site/server/api/reg-search.ts b/web/site/server/api/reg-search.ts
deleted file mode 100644
index c25ce408..00000000
--- a/web/site/server/api/reg-search.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-export default defineEventHandler(async (event) => {
- const config = useRuntimeConfig(event) // get config
- const path = event.path.split('?')[1] // intercept request url and split at '?', this returns all query params set from
- setResponseHeaders(event, {
- 'Access-Control-Allow-Methods': 'GET',
- 'Access-Control-Allow-Origin': '*'
- })
- try {
- // must currently include full url up to '?', all query parameters handled by web component
- return await $fetch(
- `http://bcregistry-sandbox.apigee.net/registry-search/api/v1/businesses/search/facets?${path}`,
- // apply required headers from config
- {
- headers: {
- Accept: 'application/json',
- 'x-apikey': config.xApiKey,
- 'account-id': config.accountId
- }
- }
- )
- } catch (error) {
- throw createError({
- statusCode: 400,
- message: 'Error Fetching Businesses'
- })
- }
-})