@dhis2/create-app 5.4.0-alpha.1 → 5.4.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,89 @@
1
+ const test = require('tape')
2
+ const {
3
+ isGitTemplateSpecifier,
4
+ parseGitTemplateSpecifier,
5
+ } = require('../src/utils/isGitTemplateSpecifier')
6
+
7
+ test('isGitTemplateSpecifier detects supported GitHub patterns', (t) => {
8
+ t.plan(7)
9
+
10
+ t.equal(isGitTemplateSpecifier('basic'), false, 'built-in key is not git')
11
+ t.equal(
12
+ isGitTemplateSpecifier('react-router'),
13
+ false,
14
+ 'second built-in key is not git'
15
+ )
16
+ t.equal(
17
+ isGitTemplateSpecifier('owner/repo'),
18
+ true,
19
+ 'owner/repo shorthand is git'
20
+ )
21
+ t.equal(
22
+ isGitTemplateSpecifier('owner/repo#main'),
23
+ true,
24
+ 'owner/repo#ref shorthand is git'
25
+ )
26
+ t.equal(
27
+ isGitTemplateSpecifier('https://github.com/owner/repo'),
28
+ true,
29
+ 'GitHub URL is git'
30
+ )
31
+ t.equal(
32
+ isGitTemplateSpecifier('owner/repo#main:templates/app'),
33
+ false,
34
+ 'subdirectory syntax is no longer supported'
35
+ )
36
+ t.equal(isGitTemplateSpecifier(''), false, 'empty source is not git')
37
+ })
38
+
39
+ test('parseGitTemplateSpecifier parses shorthand with ref', (t) => {
40
+ t.plan(5)
41
+
42
+ const parsed = parseGitTemplateSpecifier('owner/repo#main')
43
+ t.equal(parsed.owner, 'owner', 'owner parsed')
44
+ t.equal(parsed.repo, 'repo', 'repo parsed')
45
+ t.equal(parsed.ref, 'main', 'ref parsed')
46
+ t.equal(
47
+ parsed.repoUrl,
48
+ 'https://github.com/owner/repo.git',
49
+ 'repo URL normalized'
50
+ )
51
+ t.equal(parsed.raw, 'owner/repo#main', 'raw source preserved')
52
+ })
53
+
54
+ test('parseGitTemplateSpecifier parses URL and strips .git suffix', (t) => {
55
+ t.plan(4)
56
+
57
+ const parsed = parseGitTemplateSpecifier(
58
+ 'https://github.com/acme/template.git#release'
59
+ )
60
+ t.equal(parsed.owner, 'acme', 'owner parsed from URL')
61
+ t.equal(parsed.repo, 'template', 'repo parsed and .git removed')
62
+ t.equal(parsed.ref, 'release', 'ref parsed from URL')
63
+ t.equal(parsed.raw, 'https://github.com/acme/template.git#release', 'raw')
64
+ })
65
+
66
+ test('parseGitTemplateSpecifier rejects unsupported or malformed inputs', (t) => {
67
+ t.plan(4)
68
+
69
+ t.throws(
70
+ () => parseGitTemplateSpecifier('owner-only'),
71
+ /Invalid template source/,
72
+ 'rejects malformed shorthand'
73
+ )
74
+ t.throws(
75
+ () => parseGitTemplateSpecifier('https://gitlab.com/acme/repo'),
76
+ /Only github.com repositories are supported|Unsupported template host/,
77
+ 'rejects non-GitHub host'
78
+ )
79
+ t.throws(
80
+ () => parseGitTemplateSpecifier('owner/repo#'),
81
+ /Ref cannot be empty/,
82
+ 'rejects empty ref'
83
+ )
84
+ t.throws(
85
+ () => parseGitTemplateSpecifier('owner/repo#main:templates/app'),
86
+ /Invalid template source/,
87
+ 'rejects subdirectory syntax'
88
+ )
89
+ })
@@ -0,0 +1,69 @@
1
+ const os = require('node:os')
2
+ const path = require('node:path')
3
+ const fs = require('fs-extra')
4
+ const test = require('tape')
5
+ const resolveExternalTemplateSource = require('../src/utils/resolveExternalTemplateSource')
6
+ const validateTemplateDirectory = require('../src/utils/validateTemplateDirectory')
7
+
8
+ const createTempTemplate = () => {
9
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'd2-create-test-'))
10
+ fs.writeJsonSync(path.join(tempDir, 'package.json'), { name: 'fixture' })
11
+ return tempDir
12
+ }
13
+
14
+ test('validateTemplateDirectory accepts valid template directory', (t) => {
15
+ const tempDir = createTempTemplate()
16
+ t.plan(1)
17
+
18
+ try {
19
+ validateTemplateDirectory(tempDir, 'test-source')
20
+ t.pass('valid directory passes')
21
+ } finally {
22
+ fs.removeSync(tempDir)
23
+ }
24
+ })
25
+
26
+ test('resolveExternalTemplateSource fails for unknown non-git templates', async (t) => {
27
+ t.plan(1)
28
+
29
+ try {
30
+ await resolveExternalTemplateSource('unknown-template')
31
+ t.fail('should fail')
32
+ } catch (error) {
33
+ t.match(
34
+ String(error.message || error),
35
+ /Unknown template/,
36
+ 'returns unknown-template error'
37
+ )
38
+ }
39
+ })
40
+
41
+ test('resolveExternalTemplateSource fails fast for unsupported git hosts', async (t) => {
42
+ t.plan(1)
43
+
44
+ try {
45
+ await resolveExternalTemplateSource('https://gitlab.com/acme/repo')
46
+ t.fail('should fail')
47
+ } catch (error) {
48
+ t.match(
49
+ String(error.message || error),
50
+ /Unsupported template host|Only github.com repositories are supported/,
51
+ 'rejects unsupported host before clone'
52
+ )
53
+ }
54
+ })
55
+
56
+ test('resolveExternalTemplateSource rejects subdirectory syntax', async (t) => {
57
+ t.plan(1)
58
+
59
+ try {
60
+ await resolveExternalTemplateSource('owner/repo#main:templates/app')
61
+ t.fail('should fail')
62
+ } catch (error) {
63
+ t.match(
64
+ String(error.message || error),
65
+ /Unknown template|Invalid template source/,
66
+ 'subdirectory syntax is rejected'
67
+ )
68
+ }
69
+ })