Skip to content

Commit

Permalink
233: Hookup A&R to Data Register. (#267)
Browse files Browse the repository at this point in the history
* 233: Hookup A&R to Data Register.

* Remove useless declaration.

* Update const.

* Bump readme.

* Fix UT

---------

Co-authored-by: Daniel Truong <[email protected]>
  • Loading branch information
marklise and danieltruong authored Oct 30, 2023
1 parent ff506f2 commit 52f2da2
Show file tree
Hide file tree
Showing 12 changed files with 580 additions and 8 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# BC Parks Attendance & Revenue - API
![Lifecycle:Maturing](https://img.shields.io/badge/Lifecycle-Maturing-007EC6) [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=bcgov_bcparks-ar-api&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=bcgov_bcparks-ar-api)


# Introduction

This repository consists of the back end code for the BC Parks Attendance & Revenue system (A&R) API. A&R helps Park Operators, BC Parks, and the BC Government track important statistical information to help guide budget allowances and any maintenance that needs to be done to parks.
Expand Down
6 changes: 3 additions & 3 deletions __tests__/global/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"Frontcountry Camping",
"Day Use"
],
"orcs": 41,
"orcs": "41",
"subAreaName": "Maple Bay"
}
],
Expand All @@ -63,7 +63,7 @@
"Day Use"
],
"parkName": "Cultus Lake Park",
"orcs": 41,
"orcs": "41",
"subAreaName": "Maple Bay",
"roles": [
"sysadmin",
Expand All @@ -77,7 +77,7 @@
"Day Use"
],
"parkName": "Cultus Lake Park",
"orcs": 41,
"orcs": "41",
"subAreaName": "Teapot Hill",
"roles": [
"sysadmin",
Expand Down
4 changes: 3 additions & 1 deletion __tests__/global/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ const REGION = process.env.AWS_REGION || 'local-env';
const ENDPOINT = 'http://localhost:8000';
const TABLE_NAME = process.env.TABLE_NAME || 'ar-tests';
const CONFIG_TABLE_NAME = process.env.CONFIG_TABLE_NAME || 'ar-config';
const NAME_CACHE_TABLE_NAME = process.env.NAME_CACHE_TABLE_NAME || 'name-cache';

module.exports = {
REGION,
ENDPOINT,
TABLE_NAME,
CONFIG_TABLE_NAME
CONFIG_TABLE_NAME,
NAME_CACHE_TABLE_NAME
};
51 changes: 49 additions & 2 deletions __tests__/global/setup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const AWS = require('aws-sdk');

const { REGION, ENDPOINT, TABLE_NAME, CONFIG_TABLE_NAME } = require('./settings');
const { REGION, ENDPOINT, TABLE_NAME, CONFIG_TABLE_NAME, NAME_CACHE_TABLE_NAME } = require('./settings');
const { logger } = require('../../lambda/logger');

module.exports = async () => {
Expand All @@ -12,7 +12,8 @@ module.exports = async () => {
// TODO: This should pull in the JSON version of our serverless.yml!

try {
let res = await dynamoDb
console.log("Creating main table.");
await dynamoDb
.createTable({
TableName: TABLE_NAME,
KeySchema: [
Expand All @@ -33,6 +34,51 @@ module.exports = async () => {
{
AttributeName: 'sk',
AttributeType: 'S'
},
{
AttributeName: 'orcs',
AttributeType: 'S'
}
],
ProvisionedThroughput: {
ReadCapacityUnits: 1,
WriteCapacityUnits: 1
},
GlobalSecondaryIndexes: [
{
IndexName: 'orcs-index',
KeySchema: [
{
AttributeName: 'orcs',
KeyType: 'HASH'
}
],
Projection: {
ProjectionType: 'ALL'
},
ProvisionedThroughput: {
ReadCapacityUnits: 1,
WriteCapacityUnits: 1
}
}
]
})
.promise();

console.log("Creating name-cache table.");
await dynamoDb
.createTable({
TableName: NAME_CACHE_TABLE_NAME,
KeySchema: [
{
AttributeName: 'pk',
KeyType: 'HASH'
}
],
AttributeDefinitions: [
{
AttributeName: 'pk',
AttributeType: 'S'
}
],
ProvisionedThroughput: {
Expand All @@ -42,6 +88,7 @@ module.exports = async () => {
})
.promise();

console.log("Creating config table.");
await dynamoDb
.createTable({
TableName: CONFIG_TABLE_NAME,
Expand Down
7 changes: 6 additions & 1 deletion __tests__/global/teardown.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const AWS = require('aws-sdk');

const { REGION, ENDPOINT, TABLE_NAME, CONFIG_TABLE_NAME } = require('./settings');
const { REGION, ENDPOINT, TABLE_NAME, CONFIG_TABLE_NAME, NAME_CACHE_TABLE_NAME } = require('./settings');
const { logger } = require('../../lambda/logger');

module.exports = async () => {
Expand All @@ -15,6 +15,11 @@ module.exports = async () => {
TableName: TABLE_NAME
})
.promise();
await dynamoDb
.deleteTable({
TableName: NAME_CACHE_TABLE_NAME
})
.promise();
await dynamoDb
.deleteTable({
TableName: CONFIG_TABLE_NAME
Expand Down
150 changes: 150 additions & 0 deletions __tests__/name-update.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
const AWS = require("aws-sdk");
const { DocumentClient } = require("aws-sdk/clients/dynamodb");
const { REGION, ENDPOINT, TABLE_NAME, NAME_CACHE_TABLE_NAME } = require("./global/settings");
const docClient = new DocumentClient({
region: REGION,
endpoint: ENDPOINT,
convertEmptyValues: true,
});
async function setupDb() {
// Insert a document for the handler to now find and update.
await docClient
.put({
TableName: TABLE_NAME,
Item: {
"pk": "0673::Backcountry Cabins",
"sk": "201702",
"activity": "Backcountry Cabins",
"date": "201702",
"isLegacy": true,
"isLocked": true,
"lastUpdated": "2023-04-04T21:32:34.317Z",
"legacyData": {
"legacy_backcountryCabinsNetRevenue": 0,
"legacy_backcountryCabinsTotalAttendancePeople": 0
},
"orcs": "1",
"parkName": "Strathcona Park",
"subAreaId": "0673"
}
})
.promise();
}

describe("Name Update Tests", () => {
const OLD_ENV = process.env;
beforeEach(async () => {
jest.resetModules();
process.env = { ...OLD_ENV }; // Make a copy of environment
});

afterEach(() => {
process.env = OLD_ENV; // Restore old environment
});

beforeAll(async () => {
return await setupDb();
});

test("updateLocalCache", async () => {
const axios = require('axios');
jest.mock("axios");
axios.get.mockImplementation(
() => Promise.resolve({
statusCode: 200,
data: {
data: {
items: [
{
updateDate: '2023-09-18T16:54:12.574Z',
displayName: 'Strathcona Park',
createDate: '2023-09-15T17:13:14.633Z',
status: 'current',
sk: 'Details',
pk: '1',
effectiveDate: '1911-03-01',
legalName: 'Strathcona Park',
phoneticName: ''
}
]
}
}
})
);

const nameUpdateHandler = require("../lambda/nameUpdate/index");

// Cached document keys
const CACHED_DOCUMENT = {
TableName: NAME_CACHE_TABLE_NAME,
Key: {
pk: "1",
},
};

// AR document key
const AR_DOCUMENT_KEY = {
pk: "0673::Backcountry Cabins",
sk: "201702"
};

// Ensure this doesn't exist yet.
const notFoundDoc = await docClient.get(CACHED_DOCUMENT).promise();
expect(notFoundDoc).toStrictEqual({});

// Call the handler, it will have cache-miss
await nameUpdateHandler.handler({}, null);

// Expect the cache to be updated.
const doc = await docClient.get(CACHED_DOCUMENT).promise();
expect(doc.Item.pk).toBe("1");

// Change the last cached item to be different in order to trigger a displayName
// change on the handler.
const params = {
TableName: NAME_CACHE_TABLE_NAME,
Key: { pk: '1' },
UpdateExpression: 'set displayName =:displayName',
ExpressionAttributeValues: {
':displayName': 'some other park name'
}
};
await docClient.update(params).promise();
const cachedDocumentSet = await docClient.get(CACHED_DOCUMENT).promise();
expect(cachedDocumentSet.Item.displayName).toBe('some other park name');

// Also update the backcountry cabin record in the main table
const params2 = {
TableName: TABLE_NAME,
Key: AR_DOCUMENT_KEY,
UpdateExpression: 'set parkName =:parkName',
ExpressionAttributeValues: {
':parkName': 'some other park name'
}
};
await docClient.update(params2).promise();
const arDocumentSetParkName = await docClient.get({
TableName: TABLE_NAME,
Key: AR_DOCUMENT_KEY,
}).promise();

expect(arDocumentSetParkName.Item.parkName).toBe('some other park name');

// Run the update
await nameUpdateHandler.handler({}, null);

// Fetch the updated cache and check that it has been udpated
const cachedDocument = await docClient.get(CACHED_DOCUMENT).promise();

// Ensure it was updated
expect(cachedDocument.Item.displayName).toBe('Strathcona Park');

// Fetch the updated AR document and check that it has been udpated
const arDocument = await docClient.get({
TableName: TABLE_NAME,
Key: AR_DOCUMENT_KEY,
}).promise();

expect(arDocument.Item.parkName).toBe('Strathcona Park');
});
});
4 changes: 4 additions & 0 deletions lambda/dynamoUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const AWS = require("aws-sdk");
const { logger } = require("./logger");

const TABLE_NAME = process.env.TABLE_NAME || "ar-tests";
const ORCS_INDEX = process.env.ORCS_INDEX || "orcs-index";
const NAME_CACHE_TABLE_NAME = process.env.NAME_CACHE_TABLE_NAME || "name-cache";
const CONFIG_TABLE_NAME = process.env.CONFIG_TABLE_NAME || "ar-config";
const options = {
region: "ca-central-1",
Expand Down Expand Up @@ -234,6 +236,8 @@ module.exports = {
PASS_TYPE_EXPIRY_HOURS,
FISCAL_YEAR_FINAL_MONTH,
TABLE_NAME,
ORCS_INDEX,
NAME_CACHE_TABLE_NAME,
dynamodb,
runQuery,
runScan,
Expand Down
Loading

0 comments on commit 52f2da2

Please sign in to comment.