@windward/integrations 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/.editorconfig +13 -0
  2. package/.eslintrc.js +15 -0
  3. package/.prettierrc +4 -0
  4. package/README.md +19 -0
  5. package/babel.config.js +1 -0
  6. package/components/Integration/Driver/ManageAtutor.vue +143 -0
  7. package/components/Integration/Driver/ManageBase.vue +145 -0
  8. package/components/Integration/JobTable.vue +308 -0
  9. package/components/Integration/TestConnection.vue +45 -0
  10. package/config/integration.config.js +13 -0
  11. package/helpers/Driver/Atutor.ts +12 -0
  12. package/helpers/Driver/BaseDriver.ts +25 -0
  13. package/helpers/Driver/DriverInterface.ts +7 -0
  14. package/helpers/IntegrationHelper.ts +150 -0
  15. package/i18n/en-US/components/index.ts +7 -0
  16. package/i18n/en-US/components/integration/driver.ts +18 -0
  17. package/i18n/en-US/components/integration/index.ts +7 -0
  18. package/i18n/en-US/components/integration/job.ts +22 -0
  19. package/i18n/en-US/components/navigation/index.ts +5 -0
  20. package/i18n/en-US/components/navigation/integrations.ts +8 -0
  21. package/i18n/en-US/index.ts +16 -0
  22. package/i18n/en-US/modules/index.ts +5 -0
  23. package/i18n/en-US/pages/importContent.ts +3 -0
  24. package/i18n/en-US/pages/importCourse.ts +13 -0
  25. package/i18n/en-US/pages/index.ts +9 -0
  26. package/i18n/en-US/pages/vendor.ts +11 -0
  27. package/i18n/en-US/shared/error.ts +8 -0
  28. package/i18n/en-US/shared/index.ts +11 -0
  29. package/i18n/en-US/shared/menu.ts +3 -0
  30. package/i18n/en-US/shared/permission.ts +26 -0
  31. package/i18n/en-US/shared/settings.ts +1 -0
  32. package/jest.config.js +17 -0
  33. package/models/CourseSectionIntegration.ts +12 -0
  34. package/models/IntegrationJob.ts +12 -0
  35. package/models/Organization.ts +14 -0
  36. package/models/OrganizationIntegration.ts +17 -0
  37. package/models/RemoteContent.ts +12 -0
  38. package/models/RemoteCourse.ts +17 -0
  39. package/models/RemoteOrganization.ts +17 -0
  40. package/models/Vendor.ts +12 -0
  41. package/package.json +44 -0
  42. package/pages/admin/importCourse.vue +390 -0
  43. package/pages/admin/vendors.vue +241 -0
  44. package/pages/course/importContent.vue +25 -0
  45. package/plugin.js +110 -0
  46. package/test/Helpers/IntegrationHelper.spec.js +92 -0
  47. package/test/Pages/Admin/ImportCourse.spec.js +19 -0
  48. package/test/Pages/Admin/vendors.spec.js +19 -0
  49. package/test/Pages/Course/importContent.spec.js +19 -0
  50. package/test/__mocks__/lodashMock.js +31 -0
  51. package/test/__mocks__/modelMock.js +101 -0
  52. package/test/__mocks__/vuexMock.js +31 -0
  53. package/test/mocks.js +18 -0
  54. package/tsconfig.json +21 -0
package/plugin.js ADDED
@@ -0,0 +1,110 @@
1
+ import enUS from './i18n/en-US'
2
+ import AdminVendorsPage from './pages/admin/vendors.vue'
3
+ import AdminImportCoursePage from './pages/admin/importCourse.vue'
4
+ import ImportContentPage from './pages/course/importContent.vue'
5
+ import IntegrationHelper from './helpers/IntegrationHelper'
6
+
7
+ export default {
8
+ name: 'windward.integrations.name',
9
+ hooks: {
10
+ beforeContent: (body) => {
11
+ return body
12
+ },
13
+ beforeDestroy: () => {},
14
+ beforeNavigate: () => {},
15
+ onNavigate: () => {},
16
+ onLoad: (page) => {},
17
+ onContent: () => {},
18
+ },
19
+ i18n: {
20
+ 'en-US': enUS,
21
+ },
22
+ pages: [
23
+ {
24
+ page: 'admin-integrations',
25
+ path: '/admin/integrations/vendors',
26
+ i18n: 'windward.integrations.menu.integrations',
27
+ name: 'PluginIntegrationsAdminVendorsPage',
28
+ template: AdminVendorsPage,
29
+ },
30
+ {
31
+ page: 'admin-integrations',
32
+ path: '/admin/integrations/import-course',
33
+ i18n: 'windward.integrations.components.navigation.integrations.import_course',
34
+ name: 'PluginIntegrationsAdminImportCoursePage',
35
+ template: AdminImportCoursePage,
36
+ },
37
+ {
38
+ page: 'admin-integrations',
39
+ path: '/course/:course/integrations/import-content',
40
+ i18n: 'windward.integrations.components.navigation.integrations.import_content',
41
+ name: 'PluginIntegrationsImportContentPage',
42
+ template: ImportContentPage,
43
+ },
44
+ ],
45
+ components: {
46
+ menu: [
47
+ {
48
+ ref_page: 'admin',
49
+ children: [
50
+ {
51
+ i18n: 'windward.integrations.components.navigation.integrations.manage_integrations',
52
+ path: '/admin/integrations/vendors',
53
+ context: ['home'],
54
+ permissions: {
55
+ 'plugin.windward.integrations.organization.integration':
56
+ {
57
+ writable: true,
58
+ },
59
+ },
60
+ },
61
+ {
62
+ i18n: 'windward.integrations.components.navigation.integrations.import_course',
63
+ path: '/admin/integrations/import-course',
64
+ context: ['home'],
65
+ permissions: {
66
+ 'plugin.windward.integrations.course': {
67
+ writable: true,
68
+ },
69
+ },
70
+ },
71
+ {
72
+ i18n: 'windward.integrations.components.navigation.integrations.import_content',
73
+ path: '/course/{course.id}/integrations/import-content',
74
+ context: ['course'],
75
+ permissions: {
76
+ 'plugin.windward.integrations.course': {
77
+ writable: true,
78
+ },
79
+ },
80
+ },
81
+ /*
82
+ {
83
+ i18n: 'windward.integrations.components.navigation.integrations.manage_lti',
84
+ path: '/admin/integrations/lti',
85
+ context: ['home'],
86
+ permissions: {
87
+ 'plugin.windward.integrations.organization.integration': {
88
+ writable: true,
89
+ },
90
+ },
91
+ },
92
+ {
93
+ i18n: 'windward.integrations.components.navigation.integrations.manage_lti_links',
94
+ path: '/course/{course.id}/integrations/lti',
95
+ context: ['course'],
96
+ permissions: {
97
+ 'plugin.windward.integrations.organization.integration': {
98
+ writable: true,
99
+ },
100
+ },
101
+ },
102
+ */
103
+ ],
104
+ },
105
+ ],
106
+ },
107
+ services: {
108
+ Integration: IntegrationHelper,
109
+ },
110
+ }
@@ -0,0 +1,92 @@
1
+ import { shallowMount } from '@vue/test-utils'
2
+ import Vue from 'vue'
3
+ import Vuetify from 'vuetify'
4
+ import { defaultMocks } from '@/test/mocks'
5
+
6
+ import '../__mocks__/vuexMock'
7
+ import '../__mocks__/modelMock'
8
+ import '../__mocks__/lodashMock'
9
+ import '@windward/core/test/__mocks__/componentsMock.js'
10
+ import IntegrationHelper from '@/helpers/IntegrationHelper'
11
+
12
+ Vue.use(Vuetify)
13
+
14
+ const Helper = new IntegrationHelper(null)
15
+ // Hard set _vendors since we can't load via api
16
+ Helper._vendors = [
17
+ {
18
+ id: '00000000-0000-0000-0000-000000000000',
19
+ product_code: 'atutor',
20
+ },
21
+ ]
22
+ Helper._loaded = true
23
+
24
+ describe('IntegrationHelper ', () => {
25
+ test('get vendors', () => {
26
+ const vendors = Helper.getVendors()
27
+
28
+ expect(vendors).toBeTruthy()
29
+ expect(vendors.length > 0).toBeTruthy()
30
+ })
31
+
32
+ test('getVendorConfig', () => {
33
+ const config = Helper.getVendorConfig(
34
+ '00000000-0000-0000-0000-000000000000'
35
+ )
36
+
37
+ expect(config).toBeTruthy()
38
+ })
39
+
40
+ test('getVendorConfig check for driver', () => {
41
+ const config = Helper.getVendorConfig(
42
+ '00000000-0000-0000-0000-000000000000'
43
+ )
44
+
45
+ expect(config).toBeTruthy()
46
+ expect(config.driver).toBeTruthy()
47
+ })
48
+
49
+ test('getVendorDriver', () => {
50
+ const driver = Helper.getVendorDriver(
51
+ '00000000-0000-0000-0000-000000000000'
52
+ )
53
+
54
+ expect(driver).toBeTruthy()
55
+ })
56
+
57
+ test('check vendor driver for components', () => {
58
+ const driver = Helper.getVendorDriver(
59
+ '00000000-0000-0000-0000-000000000000'
60
+ )
61
+
62
+ expect(driver.components).toBeTruthy()
63
+ const components = driver.components()
64
+ expect(components.Manage).toBeTruthy()
65
+ })
66
+
67
+ test('check vendor driver component mount', () => {
68
+ const driver = Helper.getVendorDriver(
69
+ '00000000-0000-0000-0000-000000000000'
70
+ )
71
+ const components = driver.components()
72
+
73
+ const wrapper = shallowMount(components.Manage, {
74
+ vuetify: new Vuetify(),
75
+ mocks: defaultMocks,
76
+ propsData: {
77
+ vendor: {
78
+ id: '00000000-0000-0000-0000-000000000000',
79
+ },
80
+ },
81
+ })
82
+ expect(wrapper.vm).toBeTruthy()
83
+ })
84
+
85
+ test('getVendorManageComponent', () => {
86
+ const component = Helper.getVendorManageComponent(
87
+ '00000000-0000-0000-0000-000000000000'
88
+ )
89
+
90
+ expect(component).toBeTruthy()
91
+ })
92
+ })
@@ -0,0 +1,19 @@
1
+ import { shallowMount } from '@vue/test-utils'
2
+
3
+ import Vue from 'vue'
4
+ import Vuetify from 'vuetify'
5
+ import { defaultMocks } from '@/test/mocks'
6
+
7
+ import ImportCoursePage from '@/pages/admin/importCourse.vue'
8
+
9
+ Vue.use(Vuetify)
10
+
11
+ describe('ImportCoursePage', () => {
12
+ test('ImportCoursePage is a Vue instance', () => {
13
+ const wrapper = shallowMount(ImportCoursePage, {
14
+ vuetify: new Vuetify(),
15
+ mocks: defaultMocks,
16
+ })
17
+ expect(wrapper.vm).toBeTruthy()
18
+ })
19
+ })
@@ -0,0 +1,19 @@
1
+ import { shallowMount } from '@vue/test-utils'
2
+
3
+ import Vue from 'vue'
4
+ import Vuetify from 'vuetify'
5
+ import { defaultMocks } from '@/test/mocks'
6
+
7
+ import VendorsPage from '@/pages/admin/vendors.vue'
8
+
9
+ Vue.use(Vuetify)
10
+
11
+ describe('VendorsPage', () => {
12
+ test('VendorsPage is a Vue instance', () => {
13
+ const wrapper = shallowMount(VendorsPage, {
14
+ vuetify: new Vuetify(),
15
+ mocks: defaultMocks,
16
+ })
17
+ expect(wrapper.vm).toBeTruthy()
18
+ })
19
+ })
@@ -0,0 +1,19 @@
1
+ import { shallowMount } from '@vue/test-utils'
2
+
3
+ import Vue from 'vue'
4
+ import Vuetify from 'vuetify'
5
+ import { defaultMocks } from '@/test/mocks'
6
+
7
+ import ImportContentPage from '@/pages/course/importContent.vue'
8
+
9
+ Vue.use(Vuetify)
10
+
11
+ describe('ImportContentPage', () => {
12
+ test('ImportContentPage is a Vue instance', () => {
13
+ const wrapper = shallowMount(ImportContentPage, {
14
+ vuetify: new Vuetify(),
15
+ mocks: defaultMocks,
16
+ })
17
+ expect(wrapper.vm).toBeTruthy()
18
+ })
19
+ })
@@ -0,0 +1,31 @@
1
+ jest.mock(
2
+ 'lodash',
3
+ () => {
4
+ return {
5
+ cloneDeep: (v) => {
6
+ return JSON.parse(JSON.stringify(v))
7
+ },
8
+ isEmpty: () => {
9
+ return jest.fn()
10
+ },
11
+ flatten: () => {
12
+ return jest.fn()
13
+ },
14
+ get(obj, path) {
15
+ const paths = path.split('.')
16
+ let current = obj
17
+ let i
18
+
19
+ for (i = 0; i < paths.length; ++i) {
20
+ if (typeof current[paths[i]] === 'undefined') {
21
+ return undefined
22
+ } else {
23
+ current = current[paths[i]]
24
+ }
25
+ }
26
+ return current
27
+ },
28
+ }
29
+ },
30
+ { virtual: true }
31
+ )
@@ -0,0 +1,101 @@
1
+ import { Model as mockModel } from 'vue-api-query'
2
+
3
+ import axios from 'axios'
4
+ jest.mock('axios')
5
+ mockModel.$http = axios
6
+
7
+ jest.mock('axios')
8
+
9
+ // Define any new model mocks here. The imports / mocks will be auto-generated below
10
+ const mockVirtualModels = []
11
+
12
+ const mockModels = [
13
+ { path: '../../models/Organization', resource: 'organizations' },
14
+ {
15
+ path: '../../models/OrganizationIntegration',
16
+ resource: 'organization-integrations',
17
+ },
18
+ {
19
+ path: '../../models/CourseSectionIntegration',
20
+ resource: 'section-integrations',
21
+ },
22
+ { path: '../../models/IntegrationJob', resource: 'integration-jobs' },
23
+ { path: '../../models/RemoteContent', resource: 'remote-content' },
24
+ { path: '../../models/RemoteCourse', resource: 'remote-courses' },
25
+ {
26
+ path: '../../models/RemoteOrganization',
27
+ resource: 'remote-organizations',
28
+ },
29
+ { path: '../../models/Vendor', resource: 'vendors' },
30
+ ]
31
+
32
+ // DO NOT ALTER THE BELOW CODE
33
+ jest.mock('', () => {
34
+ return {
35
+ __esModule: true,
36
+ default: class Model {},
37
+ }
38
+ })
39
+ class mockBaseModel extends mockModel {
40
+ baseURL() {
41
+ return 'http://windwardapi.local'
42
+ }
43
+
44
+ request(config) {
45
+ return new Promise((resolve) => {
46
+ resolve({ data: {} })
47
+ })
48
+ }
49
+ }
50
+
51
+ jest.mock(
52
+ '~/models/Model',
53
+ () => {
54
+ return {
55
+ __esModule: true,
56
+ default: class Model extends mockBaseModel {},
57
+ }
58
+ },
59
+ { virtual: true }
60
+ )
61
+
62
+ for (let mockI = 0; mockI < mockVirtualModels.length; mockI++) {
63
+ jest.mock(
64
+ mockVirtualModels[mockI].path,
65
+ () => {
66
+ return {
67
+ __esModule: true,
68
+ default: class Model extends mockBaseModel {
69
+ resource() {
70
+ return (
71
+ mockVirtualModels[mockI].resource ||
72
+ this.constructor.name
73
+ )
74
+ }
75
+ },
76
+ }
77
+ },
78
+ { virtual: true }
79
+ )
80
+ }
81
+
82
+ for (let mockJ = 0; mockJ < mockModels.length; mockJ++) {
83
+ jest.mock(mockModels[mockJ].path, () => {
84
+ return {
85
+ __esModule: true,
86
+ default: class Model extends mockBaseModel {
87
+ resource() {
88
+ return mockModels[mockJ].resource || this.constructor.name
89
+ }
90
+
91
+ integrations() {
92
+ return this
93
+ }
94
+
95
+ get() {
96
+ return []
97
+ }
98
+ },
99
+ }
100
+ })
101
+ }
@@ -0,0 +1,31 @@
1
+ jest.mock(
2
+ 'vuex',
3
+ () => {
4
+ return {
5
+ __esModule: true,
6
+ mapGetters(obj) {
7
+ const getters = {}
8
+ for (const [key, value] of Object.entries(obj)) {
9
+ // Return a function getter since mapGetters only work in the computed section
10
+ getters[key] = () => {
11
+ return { id: '00000000-0000-0000-0000-000000000000' }
12
+ }
13
+ }
14
+ // Just return an empty object
15
+ return getters
16
+ },
17
+ mapMutations(obj) {
18
+ const getters = {}
19
+ for (const [key, value] of Object.entries(obj)) {
20
+ // Return a function getter since mapGetters only work in the computed section
21
+ getters[key] = () => {
22
+ return { id: '00000000-0000-0000-0000-000000000000' }
23
+ }
24
+ }
25
+ // Just return an empty object
26
+ return getters
27
+ },
28
+ }
29
+ },
30
+ { virtual: true }
31
+ )
package/test/mocks.js ADDED
@@ -0,0 +1,18 @@
1
+ import { defaultMocks as mocks } from '@windward/core/test/mocks'
2
+
3
+ require('./__mocks__/modelMock')
4
+
5
+ mocks.$Integration = {
6
+ async load() {
7
+ return await new Promise((resolve) => {
8
+ resolve(true)
9
+ })
10
+ },
11
+ async getVendors() {
12
+ return await new Promise((resolve) => {
13
+ resolve([])
14
+ })
15
+ },
16
+ }
17
+
18
+ export const defaultMocks = mocks
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2018",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Node",
6
+ "lib": ["ESNext", "ESNext.AsyncIterable", "DOM"],
7
+ "esModuleInterop": true,
8
+ "allowJs": true,
9
+ "sourceMap": true,
10
+ "strict": true,
11
+ "noEmit": true,
12
+ "experimentalDecorators": true,
13
+ "baseUrl": ".",
14
+ "paths": {
15
+ "~/*": ["./*"],
16
+ "@/*": ["./*"]
17
+ },
18
+ "types": ["@types/node"]
19
+ },
20
+ "exclude": ["node_modules", ".nuxt", "dist"]
21
+ }