UNPKG

5.04 kBPlain TextView Raw
1import { fixture } from './test-functions'
2
3import PythonParser, { RequirementType } from '../src/PythonParser'
4import { ComputerLanguage, OperatingSystem, Person, SoftwarePackage } from '@stencila/schema'
5
6import MockUrlFetcher from './MockUrlFetcher'
7
8const urlFetcher = new MockUrlFetcher()
9
10describe('PythonParser', () => {
11 /**
12 * When applied to an empty folder, parse should return null.
13 */
14 test('parse:empty', async () => {
15 const parser = new PythonParser(urlFetcher, fixture('empty'))
16 expect(await parser.parse()).toBeNull()
17 })
18
19 /**
20 * When applied to a folder with no Python code, parse should return null.
21 */
22 test('parse:non-py', async () => {
23 const parser = new PythonParser(urlFetcher, fixture('r-date'))
24 expect(await parser.parse()).toBeNull()
25 })
26
27 /**
28 * requirements.txt parsing should work with all features, skipping comment lines, recursive parsing, and allowing URL
29 * bases requirements
30 */
31 test('parse:py-requirements', async () => {
32 const parser = new PythonParser(urlFetcher, fixture('py-requirements'))
33
34 const requirementsContent = await parser.parseRequirementsFile('requirements.txt')
35
36 const expected = [
37 {
38 value: 'Django',
39 version: '==1.9.2',
40 type: RequirementType.Named
41 },
42 {
43 'type': RequirementType.Named,
44 'value': 'requests',
45 'version': '==2.19.1'
46 },
47 {
48 'type': RequirementType.Named,
49 'value': 'less-than',
50 'version': '<1'
51 },
52 {
53 'type': RequirementType.Named,
54 'value': 'greater-than',
55 'version': '>2'
56 },
57 {
58 'type': RequirementType.Named,
59 'value': 'less-than-equal',
60 'version': '<=3'
61 },
62 {
63 'type': RequirementType.Named,
64 'value': 'greater-than-equal',
65 'version': '>=4'
66 },
67 {
68 'type': RequirementType.Named,
69 'value': 'multiple-things',
70 'version': '>5,<=6'
71 },
72 {
73 'type': RequirementType.Named,
74 'value': 'squiggly-boye',
75 'version': '~=7'
76 },
77 {
78 'type': RequirementType.URL,
79 'value': 'svn+http://myrepo/svn/MyApp#egg=MyApp'
80 },
81 {
82 'type': RequirementType.Named,
83 'value': 'final-requirement',
84 'version': '==2.4'
85 }
86 ]
87
88 expect(requirementsContent).toEqual(expected)
89 })
90
91 /**
92 * When applied to a folder with a requirements file,
93 * parse should return the SoftwareEnvironment.
94 */
95 test('parse:py-requirements', async () => {
96 const parser = new PythonParser(urlFetcher, fixture('py-mixed'))
97
98 const arrowPackage = new SoftwarePackage()
99 arrowPackage.name = 'arrow'
100 arrowPackage.version = '==0.12.1'
101 arrowPackage.runtimePlatform = 'Python'
102 arrowPackage.programmingLanguages = [ComputerLanguage.py]
103
104 // This data is populated by the metadata lookup and the `got` mock
105 arrowPackage.authors = [Person.fromText('Joe Bloggs <joe.bloggs@example.com>')]
106 arrowPackage.operatingSystems = [OperatingSystem.windows, OperatingSystem.linux, OperatingSystem.macos,
107 OperatingSystem.unix]
108 arrowPackage.codeRepository = 'http://www.example.com/project'
109 arrowPackage.applicationCategories = ['Database', 'Software Development']
110 arrowPackage.applicationSubCategories = ['Front-Ends', 'Libraries']
111 arrowPackage.keywords = 'test keywords list'
112 arrowPackage.license = 'Free Software License'
113 arrowPackage.description = 'This is the long description that will be used in priority over description'
114
115 const environ = new SoftwarePackage()
116 environ.name = 'py-mixed'
117 environ.softwareRequirements = [arrowPackage]
118 environ.runtimePlatform = 'Python'
119
120 expect(await parser.parse()).toEqual(environ)
121 })
122
123 /**
124 * The parser should be able to go through a directory of Python files without a requirements.txt file and understand
125 * the imports that are required by parsing the source files directly.
126 */
127 test('parse:py-source', async () => {
128 const parser = new PythonParser(urlFetcher, fixture('py-source'))
129 const environ = await parser.parse()
130 expect(environ).not.toBeNull()
131 const requirementNames = environ!.softwareRequirements.map(requirement => requirement.name)
132 expect(requirementNames.length).toEqual(2)
133 expect(requirementNames).toContain('django')
134 expect(requirementNames).toContain('requests')
135 })
136
137 /**
138 * If a directory has both a `requirements.txt` file and Python source files, the `PythonParser` should only read
139 * requirements from the `requirements.txt` and should not parse the source code.
140 */
141 test('parse:py-mixed', async () => {
142 const parser = new PythonParser(urlFetcher, fixture('py-mixed'))
143 const environ = await parser.parse()
144 expect(environ).not.toBeNull()
145
146 expect(environ!.softwareRequirements.length).toEqual(1)
147 expect(environ!.softwareRequirements[0].name).toEqual('arrow')
148 expect(environ!.softwareRequirements[0].version).toEqual('==0.12.1')
149 })
150})