test: setup Mocha and ask-sdk-test suite for Malayalam calendar skill
This commit is contained in:
@@ -7,3 +7,31 @@
|
||||
or
|
||||
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
+6
-1
@@ -5,12 +5,17 @@
|
||||
"main": "src/index.mjs",
|
||||
"scripts": {
|
||||
"start": "node src/index.mjs",
|
||||
"test": "node tests/test-local.mjs",
|
||||
"test": "mocha \"tests/**/*.spec.mjs\"",
|
||||
"build": "powershell -ExecutionPolicy Bypass -File ./scripts/build.ps1",
|
||||
"deploy": "powershell -ExecutionPolicy Bypass -File ./scripts/deploy.ps1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ask-sdk-core": "^2.14.0",
|
||||
"ask-sdk-model": "^1.86.0",
|
||||
"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()
|
||||
};
|
||||
}
|
||||
+18
-26
@@ -1,5 +1,5 @@
|
||||
import Alexa from 'ask-sdk-core';
|
||||
import { Kollavarsham } from 'kollavarsham';
|
||||
import { getMalayalamDate } from './calendar.mjs';
|
||||
|
||||
// 1. Core Logic: Handles explicit date/star question requests
|
||||
const GetMalayalamDateIntentHandler = {
|
||||
@@ -88,21 +88,12 @@ function getIstDate() {
|
||||
// Formats into MM/DD/YYYY in IST
|
||||
const [{ value: month }, , { value: day }, , { value: year }] = formatter.formatToParts(now);
|
||||
|
||||
// Create UTC date anchored at noon for that IST date
|
||||
return new Date(Date.UTC(year, month - 1, day, 12, 0, 0));
|
||||
// Create UTC date anchored at 0:00:00 for that IST date
|
||||
// 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.)
|
||||
@@ -110,28 +101,29 @@ function getMalayalamDate(gregorianDate) {
|
||||
* @returns {string} - Ordinal string (e.g., "4th")
|
||||
*/
|
||||
function getOrdinalDay(day) {
|
||||
const suffixes = ['th', 'st', 'nd', 'rd'];
|
||||
const remainder = day % 100;
|
||||
if (remainder >= 11 && remainder <= 13) return `${day}th`;
|
||||
|
||||
// Handles special cases 11th, 12th, 13th
|
||||
const suffix = (remainder >= 11 && remainder <= 13)
|
||||
? 'th'
|
||||
: (suffixes[day % 10] || 'th');
|
||||
const lastDigit = day % 10;
|
||||
if (lastDigit === 1) return `${day}st`;
|
||||
if (lastDigit === 2) return `${day}nd`;
|
||||
if (lastDigit === 3) return `${day}rd`;
|
||||
|
||||
return `${day}${suffix}`;
|
||||
return `${day}th`;
|
||||
}
|
||||
|
||||
|
||||
// 3. Central Response Builder
|
||||
function generateCalendarResponse(handlerInput) {
|
||||
const kollavarshamDate = getMalayalamDate(getIstDate());
|
||||
const date = getMalayalamDate(getIstDate());
|
||||
|
||||
// Property mappings for kollavarsham package:
|
||||
const dayNum = kollavarshamDate.date; // Numeric date (e.g. 4)
|
||||
const month = kollavarshamDate.masaName; // Transliterated English month (e.g. "Karkidakam")
|
||||
const star = kollavarshamDate.naksatraName; // Transliterated English Nakshatra (e.g. "Uthram")
|
||||
const year = kollavarshamDate.year; // Malayalam Year (e.g. 1201)
|
||||
const dayNum = date.day; // Numeric date (e.g. 4)
|
||||
const month = date.month; // Transliterated English month (e.g. "Karkidakam")
|
||||
const star = date.naksatra; // Transliterated English Nakshatra (e.g. "Uthram")
|
||||
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
|
||||
.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