From d78d450709eecfa00c284fc1e6c3197dc1ae3270 Mon Sep 17 00:00:00 2001
From: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com>
Date: Sat, 20 Apr 2024 01:15:57 +0530
Subject: [PATCH 1/8] add tests for UserTypeDisplay.vue
---
.../views/__tests__/UserTypeDisplay.spec.js | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 kolibri/core/assets/src/views/__tests__/UserTypeDisplay.spec.js
diff --git a/kolibri/core/assets/src/views/__tests__/UserTypeDisplay.spec.js b/kolibri/core/assets/src/views/__tests__/UserTypeDisplay.spec.js
new file mode 100644
index 00000000000..6d228d875c0
--- /dev/null
+++ b/kolibri/core/assets/src/views/__tests__/UserTypeDisplay.spec.js
@@ -0,0 +1,45 @@
+import VueRouter from 'vue-router';
+import { render, screen } from '@testing-library/vue';
+import UserTypeDisplay from '../UserTypeDisplay.vue';
+
+const sampleUserType = 'testing-user-type';
+const translatedSampleUserType = 'Testing User Type';
+
+// Helper function to render the component with the provided props
+const renderComponent = props => {
+ const translatedUserKinds = {
+ computed: {
+ typeDisplayMap() {
+ return {
+ [sampleUserType]: translatedSampleUserType,
+ };
+ },
+ },
+ };
+
+ return render(UserTypeDisplay, {
+ routes: new VueRouter(),
+ props: {
+ userType: sampleUserType,
+ ...props,
+ },
+ mixins: [translatedUserKinds],
+ });
+};
+
+describe('UserTypeDisplay', () => {
+ test('smoke test (renders the translated user type correctly)', () => {
+ renderComponent({ userType: sampleUserType });
+ expect(screen.getByText(translatedSampleUserType)).toBeInTheDocument();
+ });
+
+ test('does not render the untranslated user type', () => {
+ renderComponent({ userType: sampleUserType });
+ expect(screen.queryByText(sampleUserType)).not.toBeInTheDocument();
+ });
+
+ test('does not render anything if the userType prop is not provided', () => {
+ const { container } = renderComponent({ userType: undefined });
+ expect(container).toBeEmptyDOMElement();
+ });
+});
From e60ed4a818636a478f12576c98e325a7eb707043 Mon Sep 17 00:00:00 2001
From: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com>
Date: Wed, 24 Apr 2024 00:41:34 +0530
Subject: [PATCH 2/8] add tests for FocusTrap
---
.../src/views/__tests__/FocusTrap.spec.js | 60 +++++++++++++++++++
1 file changed, 60 insertions(+)
create mode 100644 kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
diff --git a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
new file mode 100644
index 00000000000..f05b5d0dc7e
--- /dev/null
+++ b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
@@ -0,0 +1,60 @@
+import { render } from '@testing-library/vue';
+import userEvent from '@testing-library/user-event';
+import VueRouter from 'vue-router';
+import FocusTrap from '../FocusTrap.vue';
+
+const renderComponent = (props = {}) => {
+ return render(FocusTrap, {
+ props: {
+ disabled: false,
+ ...props,
+ },
+ routes: new VueRouter(),
+ });
+};
+
+describe('FocusTrap', () => {
+ it('should emit the "shouldFocusFirstEl" element when the tab key is pressed once', async () => {
+ const { emitted } = renderComponent();
+
+ await userEvent.tab();
+ expect(emitted()).toHaveProperty('shouldFocusFirstEl');
+ expect(emitted().shouldFocusFirstEl.length).toBe(1);
+ });
+
+ it("should trap the focus ('shouldFocusFirstEl' should be emitted twice) on pressing tab twice ", async () => {
+ const { emitted } = renderComponent();
+
+ await userEvent.tab();
+ await userEvent.tab();
+
+ expect(emitted()).toHaveProperty('shouldFocusFirstEl');
+ expect(emitted().shouldFocusFirstEl.length).toBe(2);
+ });
+
+ it('should emit "shouldFocusLastEl" when the element is subsequently focused after the inital focus', async () => {
+ const { emitted } = renderComponent();
+
+ await userEvent.tab();
+ await userEvent.tab();
+
+ // Shift + Tab is used to focus on the initial element again
+ await userEvent.tab({ shift: true });
+
+ expect(emitted()).toHaveProperty('shouldFocusLastEl');
+ expect(emitted().shouldFocusLastEl.length).toBe(1);
+ });
+
+ it("should not trap focus when 'disabled' prop is set to true", async () => {
+ const { emitted } = renderComponent({ disabled: true });
+
+ await userEvent.tab();
+ expect(emitted()).not.toHaveProperty('shouldFocusFirstEl');
+
+ await userEvent.tab();
+ expect(emitted()).not.toHaveProperty('shouldFocusFirstEl');
+
+ await userEvent.tab({ shift: true });
+ expect(emitted()).not.toHaveProperty('shouldFocusLastEl');
+ });
+});
From 8ada86e218b718416248128e01f1167bf7dec735 Mon Sep 17 00:00:00 2001
From: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com>
Date: Wed, 24 Apr 2024 01:22:23 +0530
Subject: [PATCH 3/8] add tests for TimeDuration
---
.../core/assets/src/views/TimeDuration.vue | 2 +-
.../src/views/__tests__/TimeDuration.spec.js | 57 +++++++++++++++++++
2 files changed, 58 insertions(+), 1 deletion(-)
create mode 100644 kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
diff --git a/kolibri/core/assets/src/views/TimeDuration.vue b/kolibri/core/assets/src/views/TimeDuration.vue
index bf11b7fdf73..02a638896fe 100644
--- a/kolibri/core/assets/src/views/TimeDuration.vue
+++ b/kolibri/core/assets/src/views/TimeDuration.vue
@@ -1,7 +1,7 @@
diff --git a/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js b/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
new file mode 100644
index 00000000000..a7bf5bb2d13
--- /dev/null
+++ b/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
@@ -0,0 +1,57 @@
+import { render, screen } from '@testing-library/vue';
+import VueRouter from 'vue-router';
+import TimeDuration from '../TimeDuration.vue';
+
+const renderComponent = (props = {}) => {
+ return render(TimeDuration, {
+ props,
+ routes: new VueRouter(),
+ });
+};
+
+const MINUTE = 60;
+const HOUR = 60 * MINUTE;
+const DAY = 24 * HOUR;
+
+const testCases = [
+ // Under 2 minutes, should show seconds
+ { seconds: 0, expected: '0 seconds' },
+ { seconds: 1, expected: '1 second' },
+ { seconds: 59, expected: '59 seconds' },
+ { seconds: MINUTE, expected: '60 seconds' },
+ { seconds: 2 * MINUTE - 1, expected: '119 seconds' },
+
+ // Under 1 hour, should show minutes (rounded down)
+ { seconds: 2 * MINUTE, expected: '2 minutes' },
+ { seconds: 30 * MINUTE, expected: '30 minutes' },
+ { seconds: 30 * MINUTE + 1, expected: '30 minutes' },
+ { seconds: 30 * MINUTE + 59, expected: '30 minutes' },
+ { seconds: 59 * MINUTE, expected: '59 minutes' },
+
+ // Under 1 day, should show hours (rounded down)
+ { seconds: HOUR, expected: '1 hour' },
+ { seconds: 2 * HOUR, expected: '2 hours' },
+ { seconds: 23 * HOUR, expected: '23 hours' },
+ { seconds: 23 * HOUR + 59 * MINUTE, expected: '23 hours' },
+ { seconds: 23 * HOUR + 59 * MINUTE + 59, expected: '23 hours' },
+
+ // Over 1 day, should show days (rounded down)
+ { seconds: DAY, expected: '1 day' },
+ { seconds: 2 * DAY, expected: '2 days' },
+ { seconds: 6 * DAY, expected: '6 days' },
+ { seconds: 6 * DAY + 23 * HOUR + 59 * MINUTE + 59, expected: '6 days' },
+];
+
+describe('TimeDuration', () => {
+ testCases.forEach(({ seconds, expected }) => {
+ it(`should render ${expected} for ${seconds} seconds`, () => {
+ renderComponent({ seconds });
+ expect(screen.getByText(expected)).toBeInTheDocument();
+ });
+ });
+
+ it('should render empty string if seconds are not provided as props', () => {
+ renderComponent();
+ expect(screen.getByText('—')).toBeInTheDocument();
+ });
+});
From fe2d04574c32af3b26c30a4c60f25d28e5bc8fb7 Mon Sep 17 00:00:00 2001
From: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com>
Date: Wed, 1 May 2024 16:14:58 +0530
Subject: [PATCH 4/8] address review comments
---
.../src/views/__tests__/FocusTrap.spec.js | 40 +++++++++++++++++++
.../src/views/__tests__/TimeDuration.spec.js | 8 ++--
2 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
index f05b5d0dc7e..30c2106b02a 100644
--- a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
+++ b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
@@ -57,4 +57,44 @@ describe('FocusTrap', () => {
await userEvent.tab({ shift: true });
expect(emitted()).not.toHaveProperty('shouldFocusLastEl');
});
+
+ it("should reset state when 'reset' method is called", async () => {
+ // Create a wrapper component with a Reset button to call the component's public method "reset"
+ const WrapperComponent = {
+ template: `
+
+
+
+
+ `,
+ components: {
+ FocusTrap,
+ },
+ methods: {
+ reset() {
+ this.$refs.focusTrap.reset();
+ },
+ },
+ };
+
+ const { emitted } = render(WrapperComponent, {
+ routes: new VueRouter(),
+ });
+
+ // Activate the focus trap
+ await userEvent.tab();
+ await userEvent.tab();
+ await userEvent.tab({ shift: true });
+
+ // Check if the focus trap is working
+ expect(emitted()).toHaveProperty('shouldFocusLastEl');
+ expect(emitted().shouldFocusLastEl.length).toBe(1);
+
+ // Reset the focus trap
+ await userEvent.click(document.querySelector('button'));
+
+ await userEvent.tab();
+ expect(emitted()).toHaveProperty('shouldFocusFirstEl');
+ expect(emitted().shouldFocusFirstEl.length).toBe(2);
+ });
});
diff --git a/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js b/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
index a7bf5bb2d13..35247ac63ca 100644
--- a/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
+++ b/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
@@ -43,11 +43,9 @@ const testCases = [
];
describe('TimeDuration', () => {
- testCases.forEach(({ seconds, expected }) => {
- it(`should render ${expected} for ${seconds} seconds`, () => {
- renderComponent({ seconds });
- expect(screen.getByText(expected)).toBeInTheDocument();
- });
+ it.each(testCases)('should render $seconds seconds as $expected', ({ seconds, expected }) => {
+ renderComponent({ seconds });
+ expect(screen.getByText(expected)).toBeInTheDocument();
});
it('should render empty string if seconds are not provided as props', () => {
From 52ffdc7f8821311395fa4d4e2d0404f0f785eaf7 Mon Sep 17 00:00:00 2001
From: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com>
Date: Wed, 1 May 2024 20:25:31 +0530
Subject: [PATCH 5/8] add wrapper test
---
.../src/views/__tests__/FocusTrap.spec.js | 60 +++++++------------
.../src/views/__tests__/FocusTrapWrapper.vue | 29 +++++++++
.../src/views/__tests__/TimeDuration.spec.js | 2 -
.../views/__tests__/UserTypeDisplay.spec.js | 8 +--
4 files changed, 53 insertions(+), 46 deletions(-)
create mode 100644 kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
diff --git a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
index 30c2106b02a..b2b44470635 100644
--- a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
+++ b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
@@ -1,7 +1,7 @@
-import { render } from '@testing-library/vue';
+import { render, screen, fireEvent } from '@testing-library/vue';
import userEvent from '@testing-library/user-event';
-import VueRouter from 'vue-router';
import FocusTrap from '../FocusTrap.vue';
+import FocusTrapWrapper from './FocusTrapWrapper.vue';
const renderComponent = (props = {}) => {
return render(FocusTrap, {
@@ -9,7 +9,6 @@ const renderComponent = (props = {}) => {
disabled: false,
...props,
},
- routes: new VueRouter(),
});
};
@@ -58,43 +57,26 @@ describe('FocusTrap', () => {
expect(emitted()).not.toHaveProperty('shouldFocusLastEl');
});
- it("should reset state when 'reset' method is called", async () => {
- // Create a wrapper component with a Reset button to call the component's public method "reset"
- const WrapperComponent = {
- template: `
-
-
-
-
- `,
- components: {
- FocusTrap,
- },
- methods: {
- reset() {
- this.$refs.focusTrap.reset();
- },
- },
- };
-
- const { emitted } = render(WrapperComponent, {
- routes: new VueRouter(),
- });
-
- // Activate the focus trap
- await userEvent.tab();
- await userEvent.tab();
- await userEvent.tab({ shift: true });
+ // it("should reset state when 'reset' method is called", async () => {
+ // // FocusTrapWrapper is used to test the FocusTrap component's reset method
+ // // It has a button which calls the reset method of the FocusTrap component
+ // const { emitted } = render(FocusTrapWrapper);
- // Check if the focus trap is working
- expect(emitted()).toHaveProperty('shouldFocusLastEl');
- expect(emitted().shouldFocusLastEl.length).toBe(1);
+ // await fireEvent.focus(screen.getByTestId('focusTrap'));
+ // // Activate the focus trap
+ // await userEvent.tab();
+ // await userEvent.tab();
+ // await userEvent.tab({ shift: true });
- // Reset the focus trap
- await userEvent.click(document.querySelector('button'));
+ // // The focus trap should be active
+ // expect(emitted()).toHaveProperty('shouldFocusLastEl');
+ // expect(emitted().shouldFocusLastEl.length).toBe(1);
- await userEvent.tab();
- expect(emitted()).toHaveProperty('shouldFocusFirstEl');
- expect(emitted().shouldFocusFirstEl.length).toBe(2);
- });
+ // // Reset the focus trap
+ // await userEvent.click(screen.getByRole('button'));
+
+ // await userEvent.tab();
+ // expect(emitted()).toHaveProperty('shouldFocusFirstEl');
+ // expect(emitted().shouldFocusFirstEl.length).toBe(2);
+ // });
});
diff --git a/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue b/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
new file mode 100644
index 00000000000..e7f7e1a4d48
--- /dev/null
+++ b/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js b/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
index 35247ac63ca..aef30cde02b 100644
--- a/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
+++ b/kolibri/core/assets/src/views/__tests__/TimeDuration.spec.js
@@ -1,11 +1,9 @@
import { render, screen } from '@testing-library/vue';
-import VueRouter from 'vue-router';
import TimeDuration from '../TimeDuration.vue';
const renderComponent = (props = {}) => {
return render(TimeDuration, {
props,
- routes: new VueRouter(),
});
};
diff --git a/kolibri/core/assets/src/views/__tests__/UserTypeDisplay.spec.js b/kolibri/core/assets/src/views/__tests__/UserTypeDisplay.spec.js
index 6d228d875c0..98332dbf34a 100644
--- a/kolibri/core/assets/src/views/__tests__/UserTypeDisplay.spec.js
+++ b/kolibri/core/assets/src/views/__tests__/UserTypeDisplay.spec.js
@@ -1,9 +1,8 @@
-import VueRouter from 'vue-router';
import { render, screen } from '@testing-library/vue';
import UserTypeDisplay from '../UserTypeDisplay.vue';
const sampleUserType = 'testing-user-type';
-const translatedSampleUserType = 'Testing User Type';
+const expectedSampleUserType = 'Testing User Type';
// Helper function to render the component with the provided props
const renderComponent = props => {
@@ -11,14 +10,13 @@ const renderComponent = props => {
computed: {
typeDisplayMap() {
return {
- [sampleUserType]: translatedSampleUserType,
+ [sampleUserType]: expectedSampleUserType,
};
},
},
};
return render(UserTypeDisplay, {
- routes: new VueRouter(),
props: {
userType: sampleUserType,
...props,
@@ -30,7 +28,7 @@ const renderComponent = props => {
describe('UserTypeDisplay', () => {
test('smoke test (renders the translated user type correctly)', () => {
renderComponent({ userType: sampleUserType });
- expect(screen.getByText(translatedSampleUserType)).toBeInTheDocument();
+ expect(screen.getByText(expectedSampleUserType)).toBeInTheDocument();
});
test('does not render the untranslated user type', () => {
From b5ee4788a997064cc3423ae5e67b8658a07f1804 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci-lite[bot]"
<117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Date: Wed, 1 May 2024 14:57:51 +0000
Subject: [PATCH 6/8] [pre-commit.ci lite] apply automatic fixes
---
kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue b/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
index e7f7e1a4d48..478af76486c 100644
--- a/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
+++ b/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
@@ -1,4 +1,4 @@
-
From e57933e6cb054f50ca51ce2bc549eb37422aaa56 Mon Sep 17 00:00:00 2001
From: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com>
Date: Wed, 1 May 2024 22:55:46 +0530
Subject: [PATCH 7/8] change test names
---
kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
index b2b44470635..fe572ea837f 100644
--- a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
+++ b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
@@ -21,7 +21,7 @@ describe('FocusTrap', () => {
expect(emitted().shouldFocusFirstEl.length).toBe(1);
});
- it("should trap the focus ('shouldFocusFirstEl' should be emitted twice) on pressing tab twice ", async () => {
+ it("should trap the focus and emit 'shouldFocusFirstEl' if the last focusable element is focused and we focus the next element", async () => {
const { emitted } = renderComponent();
await userEvent.tab();
@@ -31,7 +31,7 @@ describe('FocusTrap', () => {
expect(emitted().shouldFocusFirstEl.length).toBe(2);
});
- it('should emit "shouldFocusLastEl" when the element is subsequently focused after the inital focus', async () => {
+ it('should trap the focus and emit "shouldFocusLastEl" when the first element is focused and we focus the previous element', async () => {
const { emitted } = renderComponent();
await userEvent.tab();
From 030017c6d4358759d266a00b4f877e6ed95ccd8c Mon Sep 17 00:00:00 2001
From: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com>
Date: Sat, 4 May 2024 00:18:13 +0530
Subject: [PATCH 8/8] remove tests for reset method
Signed-off-by: Eshaan Aggarwal <96648934+EshaanAgg@users.noreply.github.com>
---
.../src/views/__tests__/FocusTrap.spec.js | 26 +----------------
.../src/views/__tests__/FocusTrapWrapper.vue | 29 -------------------
2 files changed, 1 insertion(+), 54 deletions(-)
delete mode 100644 kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
diff --git a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
index fe572ea837f..4efdc942240 100644
--- a/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
+++ b/kolibri/core/assets/src/views/__tests__/FocusTrap.spec.js
@@ -1,7 +1,6 @@
-import { render, screen, fireEvent } from '@testing-library/vue';
+import { render } from '@testing-library/vue';
import userEvent from '@testing-library/user-event';
import FocusTrap from '../FocusTrap.vue';
-import FocusTrapWrapper from './FocusTrapWrapper.vue';
const renderComponent = (props = {}) => {
return render(FocusTrap, {
@@ -56,27 +55,4 @@ describe('FocusTrap', () => {
await userEvent.tab({ shift: true });
expect(emitted()).not.toHaveProperty('shouldFocusLastEl');
});
-
- // it("should reset state when 'reset' method is called", async () => {
- // // FocusTrapWrapper is used to test the FocusTrap component's reset method
- // // It has a button which calls the reset method of the FocusTrap component
- // const { emitted } = render(FocusTrapWrapper);
-
- // await fireEvent.focus(screen.getByTestId('focusTrap'));
- // // Activate the focus trap
- // await userEvent.tab();
- // await userEvent.tab();
- // await userEvent.tab({ shift: true });
-
- // // The focus trap should be active
- // expect(emitted()).toHaveProperty('shouldFocusLastEl');
- // expect(emitted().shouldFocusLastEl.length).toBe(1);
-
- // // Reset the focus trap
- // await userEvent.click(screen.getByRole('button'));
-
- // await userEvent.tab();
- // expect(emitted()).toHaveProperty('shouldFocusFirstEl');
- // expect(emitted().shouldFocusFirstEl.length).toBe(2);
- // });
});
diff --git a/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue b/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
deleted file mode 100644
index 478af76486c..00000000000
--- a/kolibri/core/assets/src/views/__tests__/FocusTrapWrapper.vue
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-