Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KMS-532: Create CSV output for schemes #17

Merged
merged 14 commits into from
Feb 28, 2025
49 changes: 48 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@
"@vitejs/plugin-react": "^4.1.0",
"@xmldom/xmldom": "^0.8.10",
"aws-cdk-lib": "^2.177.0",
"csv": "^6.3.11",
"date-fns": "^4.1.0",
"esbuild": "^0.19.5",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-testing-library": "^6.2.2",
"fast-xml-parser": "^4.5.1",
"html-escaper": "^3.0.3",
"lodash": "^4.17.21",
"node-http-proxy": "^0.2.4",
"postcss-scss": "^4.0.9",
"prop-types": "^15.8.1",
Expand Down
46 changes: 46 additions & 0 deletions serverless/src/getConcepts/__tests__/handler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from 'vitest'

import { getConcepts } from '@/getConcepts/handler'
import { createCsvForScheme } from '@/shared/createCsvForScheme'
import { getApplicationConfig } from '@/shared/getConfig'
import { getFilteredTriples } from '@/shared/getFilteredTriples'
import { getGcmdMetadata } from '@/shared/getGcmdMetadata'
Expand All @@ -15,6 +16,7 @@ import { processTriples } from '@/shared/processTriples'
import { toSkosJson } from '@/shared/toSkosJson'

// Mock the specified dependencies
vi.mock('@/shared/createCsvForScheme')
vi.mock('@/shared/getFilteredTriples')
vi.mock('@/shared/toSkosJson')
vi.mock('@/shared/processTriples')
Expand All @@ -33,6 +35,50 @@ describe('getConcepts', () => {
getApplicationConfig.mockReturnValue({ defaultResponseHeaders: mockDefaultHeaders })
})

describe('when format is csv', () => {
test('calls createCsvForScheme when format is csv', async () => {
const event = {
queryStringParameters: {
format: 'csv',
scheme: 'testScheme'
}
}

createCsvForScheme.mockResolvedValue('CSV content')

await getConcepts(event)

expect(createCsvForScheme).toHaveBeenCalledWith('testScheme')
})

test('calls createCsvForScheme with empty string when scheme is not provided', async () => {
const event = {
queryStringParameters: {
format: 'csv'
}
}

createCsvForScheme.mockResolvedValue('CSV content')

await getConcepts(event)

expect(createCsvForScheme).toHaveBeenCalledWith('')
})

test('does not call createCsvForScheme when format is not csv', async () => {
const event = {
queryStringParameters: {
format: 'xml',
scheme: 'testScheme'
}
}

await getConcepts(event)

expect(createCsvForScheme).not.toHaveBeenCalled()
})
})

describe('when successful', () => {
test('returns concepts by pattern', async () => {
const mockTriples = [
Expand Down
6 changes: 6 additions & 0 deletions serverless/src/getConcepts/handler.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { XMLBuilder } from 'fast-xml-parser'

import { namespaces } from '@/shared/constants/namespaces'
import { createCsvForScheme } from '@/shared/createCsvForScheme'
import { getApplicationConfig } from '@/shared/getConfig'
import { getFilteredTriples } from '@/shared/getFilteredTriples'
import { getGcmdMetadata } from '@/shared/getGcmdMetadata'
Expand Down Expand Up @@ -33,6 +34,11 @@ import { toSkosJson } from '@/shared/toSkosJson'
*/
export const getConcepts = async (event) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is up with the tests, says this line through 134 are no longer covered.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might have issue with local branch KMS-532

const { defaultResponseHeaders } = getApplicationConfig()
const { queryStringParameters = {} } = event
const { format = '', scheme = '' } = queryStringParameters
if (format === 'csv') {
return createCsvForScheme(scheme)
}

const { conceptScheme, pattern } = event?.pathParameters || {}
const { page_num: pageNumStr = '1', page_size: pageSizeStr = '2000' } = event?.queryStringParameters || {}
Expand Down
142 changes: 142 additions & 0 deletions serverless/src/shared/__tests__/buildHierarchicalCsvPaths.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import {
describe,
expect,
vi
} from 'vitest'

import { buildHierarchicalCsvPaths } from '../buildHierarchicalCsvPaths'
import { formatCsvPath } from '../formatCsvPath'
import { getNarrowers } from '../getNarrowers'
import { isCsvLongNameFlag } from '../isCsvLongNameFlag'
import { isCsvProviderUrlFlag } from '../isCsvProviderUrlFlag'

// Mock the imported functions
vi.mock('../getNarrowers')
vi.mock('../formatCsvPath')
vi.mock('../isCsvLongNameFlag')
vi.mock('../isCsvProviderUrlFlag')

describe('buildHierarchicalCsvPaths', () => {
test('should traverse the graph and return paths', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should have describe('when.....) test('should....) structure for all our tests for consistency with MMT.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

const csvHeadersCount = 3
const providerUrlsMap = {
'http://example.com/1': ['http://provider.com/1'],
'http://example.com/2': ['http://provider.com/2']
}
const longNamesMap = {
'http://example.com/1': ['Long Name 1'],
'http://example.com/2': ['Long Name 2']
}
const scheme = 'testScheme'
const rootNode = {
narrowerPrefLabel: 'Root',
uri: 'http://example.com/root'
}
const map = new Map()

getNarrowers.mockReturnValueOnce([
{
narrowerPrefLabel: 'Child1',
uri: 'http://example.com/1'
},
{
narrowerPrefLabel: 'Child2',
uri: 'http://example.com/2'
}
])

getNarrowers.mockReturnValue([])

isCsvLongNameFlag.mockReturnValue(true)
isCsvProviderUrlFlag.mockReturnValue(true)

const paths = []
// eslint-disable-next-line max-len
await buildHierarchicalCsvPaths(csvHeadersCount, providerUrlsMap, longNamesMap, scheme, rootNode, map, [], paths)

expect(paths).toHaveLength(2)
expect(paths[0]).toEqual(['Child1', 'Long Name 1', 'http://provider.com/1', '1'])
expect(paths[1]).toEqual(['Child2', 'Long Name 2', 'http://provider.com/2', '2'])
})

test('should handle nodes without long names or provider URLs', async () => {
const csvHeadersCount = 3
const providerUrlsMap = {}
const longNamesMap = {}
const scheme = 'testScheme'
const rootNode = {
narrowerPrefLabel: 'Root',
uri: 'http://example.com/root'
}
const map = new Map()

getNarrowers.mockReturnValueOnce([
{
narrowerPrefLabel: 'Child',
uri: 'http://example.com/child'
}
])

getNarrowers.mockReturnValue([])

isCsvLongNameFlag.mockReturnValue(true)
isCsvProviderUrlFlag.mockReturnValue(true)

const paths = []
// eslint-disable-next-line max-len
await buildHierarchicalCsvPaths(csvHeadersCount, providerUrlsMap, longNamesMap, scheme, rootNode, map, [], paths)

expect(paths).toHaveLength(1)
expect(paths[0]).toEqual(['Child', ' ', ' ', 'child'])
})

test('should not include paths with only one node', async () => {
const csvHeadersCount = 3
const providerUrlsMap = {}
const longNamesMap = {}
const scheme = 'testScheme'
const rootNode = {
narrowerPrefLabel: 'Root',
uri: 'http://example.com/root'
}
const map = new Map()

getNarrowers.mockReturnValue([])

const paths = []
// eslint-disable-next-line max-len
await buildHierarchicalCsvPaths(csvHeadersCount, providerUrlsMap, longNamesMap, scheme, rootNode, map, [], paths)

expect(paths).toHaveLength(0)
})

test('should format CSV path for leaf nodes', async () => {
const csvHeadersCount = 3
const providerUrlsMap = {}
const longNamesMap = {}
const scheme = 'testScheme'
const rootNode = {
narrowerPrefLabel: 'Root',
uri: 'http://example.com/root'
}
const map = new Map()

getNarrowers.mockReturnValueOnce([
{
narrowerPrefLabel: 'Child',
uri: 'http://example.com/child'
}
])

getNarrowers.mockReturnValue([])

isCsvLongNameFlag.mockReturnValue(false)
isCsvProviderUrlFlag.mockReturnValue(false)

const paths = []
// eslint-disable-next-line max-len
await buildHierarchicalCsvPaths(csvHeadersCount, providerUrlsMap, longNamesMap, scheme, rootNode, map, [], paths)

expect(formatCsvPath).toHaveBeenCalledWith(scheme, csvHeadersCount, ['Child', 'child'], true)
})
})
Loading