test: setup Mocha and ask-sdk-test suite for Malayalam calendar skill
This commit is contained in:
@@ -7,3 +7,31 @@
|
|||||||
or
|
or
|
||||||
npm test
|
npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Info
|
||||||
|
|
||||||
|
### Lunar Month
|
||||||
|
|
||||||
|
Amanta and Purnimanta are two systems of measuring lunar months.
|
||||||
|
|
||||||
|
- Amanta months begin after the new moon and end on the no moon day
|
||||||
|
- Purnimanta months start after the full moon and end on the full moon day
|
||||||
|
|
||||||
|
In Kerala, the Amanta system is followed.
|
||||||
|
|
||||||
|
- 1 Chingam (ചിങ്ങം), Aug – Sep, New Year, Onam Festival
|
||||||
|
- 2 Kanni (കന്നി), Sep – Oct, Mahanavami, Vijayadashami
|
||||||
|
- 3 Thulam (തുലാം), Oct – Nov, Monsoon retreat (Thulavarsham)
|
||||||
|
- 4 Vrischikam (വൃശ്ചികം), Nov – Dec, Sabarimala Season begins
|
||||||
|
- 5 Dhanu (ധനു), Dec – Jan, Thiruvathira Festival
|
||||||
|
- 6 Makaram (മകരം), Jan – Feb, Makaravilakku
|
||||||
|
- 7 Kumbham (കുംഭം), Feb – Mar, Maha Shivaratri
|
||||||
|
- 8 Meenam (മീനം), Mar – Apr, Temple Festivals (Pooram)
|
||||||
|
- 9 Medam (മേടം), Apr – May, Vishu (Harvest Festival)
|
||||||
|
- 10 Edavam (ഇടവം), May – Jun, Arrival of Monsoon
|
||||||
|
- 11 Mithunam (മിഥുനം), Jun – Jul, Heavy rains
|
||||||
|
- 12 Karkidakam (കർക്കടകം), Jul – Aug, Ramayana Masam, Ayurveda Season
|
||||||
|
|
||||||
|
## Reference for Comparison
|
||||||
|
|
||||||
|
https://www.drikpanchang.com/malayalam
|
||||||
|
|||||||
Generated
+3399
-5
File diff suppressed because it is too large
Load Diff
+7
-2
@@ -5,12 +5,17 @@
|
|||||||
"main": "src/index.mjs",
|
"main": "src/index.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node src/index.mjs",
|
"start": "node src/index.mjs",
|
||||||
"test": "node tests/test-local.mjs",
|
"test": "mocha \"tests/**/*.spec.mjs\"",
|
||||||
"build": "powershell -ExecutionPolicy Bypass -File ./scripts/build.ps1",
|
"build": "powershell -ExecutionPolicy Bypass -File ./scripts/build.ps1",
|
||||||
"deploy": "powershell -ExecutionPolicy Bypass -File ./scripts/deploy.ps1"
|
"deploy": "powershell -ExecutionPolicy Bypass -File ./scripts/deploy.ps1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ask-sdk-core": "^2.14.0",
|
"ask-sdk-core": "^2.14.0",
|
||||||
|
"ask-sdk-model": "^1.86.0",
|
||||||
"kollavarsham": "^2.5.4"
|
"kollavarsham": "^2.5.4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"ask-sdk-test": "^2.7.42",
|
||||||
|
"mocha": "^10.8.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Kollavarsham } from 'kollavarsham';
|
||||||
|
|
||||||
|
const kollavarsham = new Kollavarsham({
|
||||||
|
system: 'SuryaSiddhanta',
|
||||||
|
latitude: 10,
|
||||||
|
longitude: 76.2
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a Gregorian Date object into a Malayalam calendar format.
|
||||||
|
*
|
||||||
|
* @param {Date} gregorianDate
|
||||||
|
* @returns {{ year: number, month: string, day: number, naksatra: string }}
|
||||||
|
*/
|
||||||
|
export function getMalayalamDate(gregorianDate) {
|
||||||
|
const kollavarshamDate = kollavarsham.fromGregorianDate(gregorianDate);
|
||||||
|
|
||||||
|
// Safely extract nakshatra name (handles string or object returns safely)
|
||||||
|
const naksatraName =
|
||||||
|
kollavarshamDate.naksatraName ||
|
||||||
|
kollavarshamDate.naksatra?.enMalayalam ||
|
||||||
|
'';
|
||||||
|
|
||||||
|
return {
|
||||||
|
year: kollavarshamDate.year,
|
||||||
|
month: kollavarshamDate.masaName ? kollavarshamDate.masaName.trim() : '',
|
||||||
|
day: kollavarshamDate.date,
|
||||||
|
naksatra: naksatraName.trim()
|
||||||
|
};
|
||||||
|
}
|
||||||
+19
-27
@@ -1,5 +1,5 @@
|
|||||||
import Alexa from 'ask-sdk-core';
|
import Alexa from 'ask-sdk-core';
|
||||||
import { Kollavarsham } from 'kollavarsham';
|
import { getMalayalamDate } from './calendar.mjs';
|
||||||
|
|
||||||
// 1. Core Logic: Handles explicit date/star question requests
|
// 1. Core Logic: Handles explicit date/star question requests
|
||||||
const GetMalayalamDateIntentHandler = {
|
const GetMalayalamDateIntentHandler = {
|
||||||
@@ -88,21 +88,12 @@ function getIstDate() {
|
|||||||
// Formats into MM/DD/YYYY in IST
|
// Formats into MM/DD/YYYY in IST
|
||||||
const [{ value: month }, , { value: day }, , { value: year }] = formatter.formatToParts(now);
|
const [{ value: month }, , { value: day }, , { value: year }] = formatter.formatToParts(now);
|
||||||
|
|
||||||
// Create UTC date anchored at noon for that IST date
|
// Create UTC date anchored at 0:00:00 for that IST date
|
||||||
return new Date(Date.UTC(year, month - 1, day, 12, 0, 0));
|
// Month is 0-indexed in JavaScript Date constructor, so subtract 1.
|
||||||
|
// Year and date don't need adjustment.
|
||||||
|
return new Date(Date.UTC(year, month - 1, day, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kollavarsham calculation.
|
|
||||||
function getMalayalamDate(gregorianDate) {
|
|
||||||
// Initialize Kollavarsham with Surya Siddhanta system
|
|
||||||
// and default coordinates of Kollarvarsham project documentation.
|
|
||||||
const kollavarsham = new Kollavarsham({
|
|
||||||
system: 'SuryaSiddhanta',
|
|
||||||
latitude: 10,
|
|
||||||
longitude: 76.2
|
|
||||||
});
|
|
||||||
return kollavarsham.fromGregorianDate(gregorianDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a number to its ordinal string representation (1st, 2nd, 3rd, 4th, etc.)
|
* Converts a number to its ordinal string representation (1st, 2nd, 3rd, 4th, etc.)
|
||||||
@@ -110,28 +101,29 @@ function getMalayalamDate(gregorianDate) {
|
|||||||
* @returns {string} - Ordinal string (e.g., "4th")
|
* @returns {string} - Ordinal string (e.g., "4th")
|
||||||
*/
|
*/
|
||||||
function getOrdinalDay(day) {
|
function getOrdinalDay(day) {
|
||||||
const suffixes = ['th', 'st', 'nd', 'rd'];
|
|
||||||
const remainder = day % 100;
|
const remainder = day % 100;
|
||||||
|
if (remainder >= 11 && remainder <= 13) return `${day}th`;
|
||||||
|
|
||||||
// Handles special cases 11th, 12th, 13th
|
const lastDigit = day % 10;
|
||||||
const suffix = (remainder >= 11 && remainder <= 13)
|
if (lastDigit === 1) return `${day}st`;
|
||||||
? 'th'
|
if (lastDigit === 2) return `${day}nd`;
|
||||||
: (suffixes[day % 10] || 'th');
|
if (lastDigit === 3) return `${day}rd`;
|
||||||
|
|
||||||
return `${day}${suffix}`;
|
return `${day}th`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 3. Central Response Builder
|
// 3. Central Response Builder
|
||||||
function generateCalendarResponse(handlerInput) {
|
function generateCalendarResponse(handlerInput) {
|
||||||
const kollavarshamDate = getMalayalamDate(getIstDate());
|
const date = getMalayalamDate(getIstDate());
|
||||||
|
|
||||||
// Property mappings for kollavarsham package:
|
// Property mappings for kollavarsham package:
|
||||||
const dayNum = kollavarshamDate.date; // Numeric date (e.g. 4)
|
const dayNum = date.day; // Numeric date (e.g. 4)
|
||||||
const month = kollavarshamDate.masaName; // Transliterated English month (e.g. "Karkidakam")
|
const month = date.month; // Transliterated English month (e.g. "Karkidakam")
|
||||||
const star = kollavarshamDate.naksatraName; // Transliterated English Nakshatra (e.g. "Uthram")
|
const star = date.naksatra; // Transliterated English Nakshatra (e.g. "Uthram")
|
||||||
const year = kollavarshamDate.year; // Malayalam Year (e.g. 1201)
|
const year = date.year; // Malayalam Year (e.g. 1201)
|
||||||
|
|
||||||
const speechText = `Today it is the ${getOrdinalDay(dayNum)} of ${month}. Today's nakshatra is ${star}.`;
|
const speechText = `Today is the ${getOrdinalDay(dayNum)} of ${month}. The nakshatra is ${star}.`;
|
||||||
|
|
||||||
return handlerInput.responseBuilder
|
return handlerInput.responseBuilder
|
||||||
.speak(speechText)
|
.speak(speechText)
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { getMalayalamDate } from '../src/calendar.mjs';
|
||||||
|
import assert from 'node:assert';
|
||||||
|
|
||||||
|
describe('getMalayalamDate unit test', () => {
|
||||||
|
it('Conversion of date 2026-01-01 returns correct Malayalam date', () => {
|
||||||
|
const result = getMalayalamDate(new Date(2026, 0, 1, 0, 0, 0));
|
||||||
|
assert.deepStrictEqual(result, {
|
||||||
|
year: 1201,
|
||||||
|
month: 'Dhanu',
|
||||||
|
day: 17,
|
||||||
|
naksatra: 'Rohini'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { AlexaTest, LaunchRequestBuilder } from 'ask-sdk-test';
|
||||||
|
import { handler as skillHandler } from '../src/index.mjs';
|
||||||
|
|
||||||
|
const skillSettings = {
|
||||||
|
appId: 'amzn1.ask.skill.fake-app-id',
|
||||||
|
userId: 'amzn1.ask.account.fake-user-id',
|
||||||
|
deviceId: 'amzn1.ask.device.fake-device-id',
|
||||||
|
locale: 'en-US',
|
||||||
|
};
|
||||||
|
|
||||||
|
const alexaTest = new AlexaTest(skillHandler, skillSettings);
|
||||||
|
|
||||||
|
describe('Alexa Malayalam Calendar Skill', () => {
|
||||||
|
alexaTest.test([
|
||||||
|
{
|
||||||
|
request: new LaunchRequestBuilder(skillSettings).build(),
|
||||||
|
saysLike: 'Today is',
|
||||||
|
repromptsNothing: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { handler } from '../src/index.mjs';
|
|
||||||
|
|
||||||
// Mock Alexa LaunchRequest Payload
|
|
||||||
const mockAlexaLaunchRequest = {
|
|
||||||
version: '1.0',
|
|
||||||
session: {
|
|
||||||
new: true,
|
|
||||||
sessionId: 'amzn1.echo-sdk-s-session-mock-id',
|
|
||||||
application: {
|
|
||||||
applicationId: 'amzn1.ask.skill.53645cde-742f-499e-83d3-07ed537bce39'
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
userId: 'amzn1.ask.account.mockUser'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
context: {
|
|
||||||
System: {
|
|
||||||
application: {
|
|
||||||
applicationId: 'amzn1.ask.skill.53645cde-742f-499e-83d3-07ed537bce39'
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
userId: 'amzn1.ask.account.mockUser'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
request: {
|
|
||||||
type: 'LaunchRequest',
|
|
||||||
requestId: 'amzn1.echo-api.request.mockRequestId',
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
locale: 'en-US'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
async function runLocalTest() {
|
|
||||||
console.log('🚀 Running Alexa Handler Locally...\n');
|
|
||||||
try {
|
|
||||||
const response = await handler(mockAlexaLaunchRequest, {});
|
|
||||||
console.log('✅ Response Received:\n');
|
|
||||||
console.log(JSON.stringify(response, null, 2));
|
|
||||||
} catch (error) {
|
|
||||||
console.error('❌ Error executing handler locally:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
runLocalTest();
|
|
||||||
Reference in New Issue
Block a user