adapt-authoring-courseassets 1.0.5 → 1.2.0

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.
@@ -0,0 +1,15 @@
1
+ name: Tests
2
+ on: push
3
+ jobs:
4
+ default:
5
+ runs-on: ubuntu-latest
6
+ permissions:
7
+ contents: read
8
+ steps:
9
+ - uses: actions/checkout@v4
10
+ - uses: actions/setup-node@v4
11
+ with:
12
+ node-version: 'lts/*'
13
+ cache: 'npm'
14
+ - run: npm ci
15
+ - run: npm test
@@ -1,4 +1,5 @@
1
1
  import AbstractApiModule from 'adapt-authoring-api'
2
+ import { extractAssetIds } from './utils.js'
2
3
  /**
3
4
  * Module which handles courseassets automatically using on content events
4
5
  * @memberof courseassets
@@ -46,29 +47,6 @@ class CourseAssetsModule extends AbstractApiModule {
46
47
  })
47
48
  }
48
49
 
49
- /**
50
- * Search data object for asset types and retrieve _ids
51
- * @param {Object} data
52
- */
53
- extractAssetIds (schema, data, assets = []) {
54
- Object.entries(schema).forEach(([key, val]) => {
55
- if (!Object.prototype.hasOwnProperty.call(data, key)) {
56
- return
57
- }
58
- if (val.properties) {
59
- this.extractAssetIds(val.properties, data[key], assets)
60
- } else if (val?.items?.properties) {
61
- data[key].forEach(d => this.extractAssetIds(val.items.properties, d, assets))
62
- } else if ((val?._backboneForms?.type === 'Asset' || val?._backboneForms === 'Asset') && data[key]) {
63
- const v = data[key].toString()
64
- if (!v.startsWith('http://') && !v.startsWith('https://')) {
65
- assets.push(v)
66
- }
67
- }
68
- })
69
- return Array.from(new Set(assets))
70
- };
71
-
72
50
  /**
73
51
  * Handler for content event
74
52
  * @param {String} action The action performed
@@ -96,7 +74,7 @@ class CourseAssetsModule extends AbstractApiModule {
96
74
 
97
75
  const data = isModify ? arg2 : arg1
98
76
  const schema = await this.content.getSchema(this.content.schemaName, data)
99
- const ids = this.extractAssetIds(schema.built.properties, data)
77
+ const ids = extractAssetIds(schema.built.properties, data)
100
78
 
101
79
  if (!ids.length) {
102
80
  return
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Searches a data object for asset-type schema properties and collects their IDs
3
+ * @param {Object} schema The schema properties to traverse
4
+ * @param {Object} data The data object to search for asset values
5
+ * @param {Array<String>} assets Accumulator array for found asset IDs
6
+ * @return {Array<String>} Unique array of asset IDs found in the data
7
+ * @memberof courseassets
8
+ */
9
+ export function extractAssetIds (schema, data, assets = []) {
10
+ Object.entries(schema).forEach(([key, val]) => {
11
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
12
+ return
13
+ }
14
+ if (val.properties) {
15
+ extractAssetIds(val.properties, data[key], assets)
16
+ } else if (val?.items?.properties) {
17
+ data[key].forEach(d => extractAssetIds(val.items.properties, d, assets))
18
+ } else if ((val?._backboneForms?.type === 'Asset' || val?._backboneForms === 'Asset') && data[key]) {
19
+ const v = data[key].toString()
20
+ if (!v.startsWith('http://') && !v.startsWith('https://')) {
21
+ assets.push(v)
22
+ }
23
+ }
24
+ })
25
+ return Array.from(new Set(assets))
26
+ }
package/lib/utils.js ADDED
@@ -0,0 +1 @@
1
+ export { extractAssetIds } from './utils/extractAssetIds.js'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adapt-authoring-courseassets",
3
- "version": "1.0.5",
3
+ "version": "1.2.0",
4
4
  "description": "Module for managing courseassets",
5
5
  "homepage": "https://github.com/deltanetdan/adapt-authoring-courseassets",
6
6
  "license": "GPL-3.0",
@@ -10,7 +10,7 @@
10
10
  "peerDependencies": {
11
11
  "adapt-authoring-assets": "^1.3.1",
12
12
  "adapt-authoring-content": "^1.2.3",
13
- "adapt-authoring-core": "^1.7.0"
13
+ "adapt-authoring-core": "^2.0.0"
14
14
  },
15
15
  "peerDependenciesMeta": {
16
16
  "adapt-authoring-assets": {
@@ -55,5 +55,8 @@
55
55
  }
56
56
  ]
57
57
  ]
58
+ },
59
+ "scripts": {
60
+ "test": "node --test 'tests/**/*.spec.js'"
58
61
  }
59
62
  }
@@ -0,0 +1,138 @@
1
+ import { describe, it } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+
4
+ /**
5
+ * CourseAssetsModule extends AbstractApiModule which requires a running app.
6
+ * We test the extractAssetIds method logic in isolation.
7
+ */
8
+
9
+ /* ---------- inline helper: extract extractAssetIds logic ---------- */
10
+ function extractAssetIds (schema, data, assets = []) {
11
+ Object.entries(schema).forEach(([key, val]) => {
12
+ if (!Object.prototype.hasOwnProperty.call(data, key)) {
13
+ return
14
+ }
15
+ if (val.properties) {
16
+ extractAssetIds(val.properties, data[key], assets)
17
+ } else if (val?.items?.properties) {
18
+ data[key].forEach(d => extractAssetIds(val.items.properties, d, assets))
19
+ } else if ((val?._backboneForms?.type === 'Asset' || val?._backboneForms === 'Asset') && data[key]) {
20
+ const v = data[key].toString()
21
+ if (!v.startsWith('http://') && !v.startsWith('https://')) {
22
+ assets.push(v)
23
+ }
24
+ }
25
+ })
26
+ return Array.from(new Set(assets))
27
+ }
28
+
29
+ describe('CourseAssetsModule', () => {
30
+ describe('#extractAssetIds()', () => {
31
+ it('should extract asset IDs from flat schema', () => {
32
+ const schema = {
33
+ heroImage: { _backboneForms: { type: 'Asset' } }
34
+ }
35
+ const data = { heroImage: 'asset123' }
36
+ const result = extractAssetIds(schema, data)
37
+ assert.deepEqual(result, ['asset123'])
38
+ })
39
+
40
+ it('should extract asset IDs using short _backboneForms notation', () => {
41
+ const schema = {
42
+ graphic: { _backboneForms: 'Asset' }
43
+ }
44
+ const data = { graphic: 'asset456' }
45
+ const result = extractAssetIds(schema, data)
46
+ assert.deepEqual(result, ['asset456'])
47
+ })
48
+
49
+ it('should skip HTTP URLs', () => {
50
+ const schema = {
51
+ image: { _backboneForms: 'Asset' }
52
+ }
53
+ const data = { image: 'http://example.com/img.png' }
54
+ const result = extractAssetIds(schema, data)
55
+ assert.deepEqual(result, [])
56
+ })
57
+
58
+ it('should skip HTTPS URLs', () => {
59
+ const schema = {
60
+ image: { _backboneForms: 'Asset' }
61
+ }
62
+ const data = { image: 'https://example.com/img.png' }
63
+ const result = extractAssetIds(schema, data)
64
+ assert.deepEqual(result, [])
65
+ })
66
+
67
+ it('should recurse into nested properties', () => {
68
+ const schema = {
69
+ _globals: {
70
+ properties: {
71
+ logo: { _backboneForms: 'Asset' }
72
+ }
73
+ }
74
+ }
75
+ const data = { _globals: { logo: 'logo123' } }
76
+ const result = extractAssetIds(schema, data)
77
+ assert.deepEqual(result, ['logo123'])
78
+ })
79
+
80
+ it('should recurse into array items', () => {
81
+ const schema = {
82
+ _items: {
83
+ items: {
84
+ properties: {
85
+ src: { _backboneForms: { type: 'Asset' } }
86
+ }
87
+ }
88
+ }
89
+ }
90
+ const data = {
91
+ _items: [
92
+ { src: 'item1' },
93
+ { src: 'item2' }
94
+ ]
95
+ }
96
+ const result = extractAssetIds(schema, data)
97
+ assert.deepEqual(result, ['item1', 'item2'])
98
+ })
99
+
100
+ it('should deduplicate asset IDs', () => {
101
+ const schema = {
102
+ img1: { _backboneForms: 'Asset' },
103
+ img2: { _backboneForms: 'Asset' }
104
+ }
105
+ const data = { img1: 'same', img2: 'same' }
106
+ const result = extractAssetIds(schema, data)
107
+ assert.deepEqual(result, ['same'])
108
+ })
109
+
110
+ it('should skip keys not present in data', () => {
111
+ const schema = {
112
+ present: { _backboneForms: 'Asset' },
113
+ missing: { _backboneForms: 'Asset' }
114
+ }
115
+ const data = { present: 'val1' }
116
+ const result = extractAssetIds(schema, data)
117
+ assert.deepEqual(result, ['val1'])
118
+ })
119
+
120
+ it('should skip falsy data values', () => {
121
+ const schema = {
122
+ image: { _backboneForms: 'Asset' }
123
+ }
124
+ const data = { image: '' }
125
+ const result = extractAssetIds(schema, data)
126
+ assert.deepEqual(result, [])
127
+ })
128
+
129
+ it('should return empty array when no assets found', () => {
130
+ const schema = {
131
+ title: { type: 'string' }
132
+ }
133
+ const data = { title: 'hello' }
134
+ const result = extractAssetIds(schema, data)
135
+ assert.deepEqual(result, [])
136
+ })
137
+ })
138
+ })
@@ -0,0 +1,112 @@
1
+ import { describe, it } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { extractAssetIds } from '../lib/utils/extractAssetIds.js'
4
+
5
+ describe('extractAssetIds()', () => {
6
+ it('should return empty array when no asset fields exist', () => {
7
+ const schema = { title: { type: 'string' } }
8
+ const data = { title: 'test' }
9
+ assert.deepEqual(extractAssetIds(schema, data), [])
10
+ })
11
+
12
+ it('should extract asset ID from _backboneForms Asset string type', () => {
13
+ const schema = { image: { _backboneForms: 'Asset' } }
14
+ const data = { image: 'abc123' }
15
+ assert.deepEqual(extractAssetIds(schema, data), ['abc123'])
16
+ })
17
+
18
+ it('should extract asset ID from _backboneForms.type Asset', () => {
19
+ const schema = { image: { _backboneForms: { type: 'Asset' } } }
20
+ const data = { image: 'abc123' }
21
+ assert.deepEqual(extractAssetIds(schema, data), ['abc123'])
22
+ })
23
+
24
+ it('should skip keys not present in data', () => {
25
+ const schema = { image: { _backboneForms: 'Asset' } }
26
+ const data = {}
27
+ assert.deepEqual(extractAssetIds(schema, data), [])
28
+ })
29
+
30
+ it('should skip falsy asset values', () => {
31
+ const schema = { image: { _backboneForms: 'Asset' } }
32
+ const data = { image: '' }
33
+ assert.deepEqual(extractAssetIds(schema, data), [])
34
+ })
35
+
36
+ it('should skip HTTP URLs', () => {
37
+ const schema = { image: { _backboneForms: 'Asset' } }
38
+ const data = { image: 'http://example.com/image.png' }
39
+ assert.deepEqual(extractAssetIds(schema, data), [])
40
+ })
41
+
42
+ it('should skip HTTPS URLs', () => {
43
+ const schema = { image: { _backboneForms: 'Asset' } }
44
+ const data = { image: 'https://example.com/image.png' }
45
+ assert.deepEqual(extractAssetIds(schema, data), [])
46
+ })
47
+
48
+ it('should recurse into nested schema properties', () => {
49
+ const schema = {
50
+ _graphic: {
51
+ properties: {
52
+ src: { _backboneForms: 'Asset' }
53
+ }
54
+ }
55
+ }
56
+ const data = { _graphic: { src: 'img123' } }
57
+ assert.deepEqual(extractAssetIds(schema, data), ['img123'])
58
+ })
59
+
60
+ it('should recurse into array items with properties', () => {
61
+ const schema = {
62
+ _items: {
63
+ items: {
64
+ properties: {
65
+ src: { _backboneForms: 'Asset' }
66
+ }
67
+ }
68
+ }
69
+ }
70
+ const data = { _items: [{ src: 'a1' }, { src: 'a2' }] }
71
+ assert.deepEqual(extractAssetIds(schema, data), ['a1', 'a2'])
72
+ })
73
+
74
+ it('should deduplicate asset IDs', () => {
75
+ const schema = {
76
+ _items: {
77
+ items: {
78
+ properties: {
79
+ src: { _backboneForms: 'Asset' }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ const data = { _items: [{ src: 'same' }, { src: 'same' }] }
85
+ assert.deepEqual(extractAssetIds(schema, data), ['same'])
86
+ })
87
+
88
+ it('should accumulate with provided assets array', () => {
89
+ const schema = { image: { _backboneForms: 'Asset' } }
90
+ const data = { image: 'new1' }
91
+ const existing = ['existing1']
92
+ const result = extractAssetIds(schema, data, existing)
93
+ assert.ok(result.includes('existing1'))
94
+ assert.ok(result.includes('new1'))
95
+ })
96
+
97
+ it('should handle toString on non-string asset values', () => {
98
+ const schema = { image: { _backboneForms: 'Asset' } }
99
+ const data = { image: { toString: () => 'obj123' } }
100
+ assert.deepEqual(extractAssetIds(schema, data), ['obj123'])
101
+ })
102
+
103
+ it('should handle multiple asset fields at the same level', () => {
104
+ const schema = {
105
+ image1: { _backboneForms: 'Asset' },
106
+ image2: { _backboneForms: { type: 'Asset' } },
107
+ title: { type: 'string' }
108
+ }
109
+ const data = { image1: 'a1', image2: 'a2', title: 'test' }
110
+ assert.deepEqual(extractAssetIds(schema, data), ['a1', 'a2'])
111
+ })
112
+ })