odac 1.4.10 → 1.4.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,14 @@
1
- /* global Odac */
2
1
  /**
3
2
  * ODAC Template - Client-Side Application
4
3
  *
5
- * This file demonstrates odac.js features including:
4
+ * This file is automatically compiled by ODAC's JS/TS pipeline.
5
+ * Write your frontend logic here — TypeScript (.ts) and plain JavaScript (.js) both work.
6
+ *
7
+ * - Place files in view/js/ to create entry points
8
+ * - Files starting with _ are ignored (use them as shared imports)
9
+ * - Output goes to public/assets/js/{name}.js
10
+ *
11
+ * Features demonstrated:
6
12
  * - AJAX page loading with Odac.loader() for smooth navigation
7
13
  * - History API integration
8
14
  * - Event delegation
@@ -0,0 +1,54 @@
1
+ const Odac = require('../../src/Odac')
2
+
3
+ describe('Odac.cache()', () => {
4
+ let mockOdac
5
+
6
+ beforeEach(() => {
7
+ mockOdac = {
8
+ Config: {request: {timeout: 1000}},
9
+ Route: {routes: {www: {}}},
10
+ Storage: {get: jest.fn(), put: jest.fn()}
11
+ }
12
+ global.Odac = mockOdac
13
+ global.__dir = '/mock'
14
+ })
15
+
16
+ afterEach(() => {
17
+ delete global.Odac
18
+ delete global.__dir
19
+ })
20
+
21
+ it('should expose cache() as a shorthand on the instance', () => {
22
+ const mockReq = {
23
+ method: 'GET',
24
+ url: '/',
25
+ headers: {host: 'www.example.com'},
26
+ connection: {remoteAddress: '127.0.0.1'},
27
+ on: jest.fn()
28
+ }
29
+ const mockRes = {on: jest.fn(), writeHead: jest.fn(), end: jest.fn()}
30
+
31
+ const ctx = Odac.instance('id', mockReq, mockRes)
32
+
33
+ expect(typeof ctx.cache).toBe('function')
34
+ })
35
+
36
+ it('should delegate to Request.cache()', () => {
37
+ const mockReq = {
38
+ method: 'GET',
39
+ url: '/',
40
+ headers: {host: 'www.example.com'},
41
+ connection: {remoteAddress: '127.0.0.1'},
42
+ on: jest.fn()
43
+ }
44
+ const mockRes = {on: jest.fn(), writeHead: jest.fn(), end: jest.fn(), finished: false}
45
+
46
+ const ctx = Odac.instance('id', mockReq, mockRes)
47
+ ctx.cache(3600)
48
+
49
+ ctx.Request.print()
50
+ const headers = mockRes.writeHead.mock.calls[0][1]
51
+ expect(headers['X-ODAC-Cache']).toBe(3600)
52
+ expect(headers['Cache-Control']).toBe('public, max-age=3600')
53
+ })
54
+ })
@@ -0,0 +1,95 @@
1
+ const OdacRequest = require('../../src/Request')
2
+
3
+ describe('Request.cache()', () => {
4
+ let req, res, request
5
+
6
+ beforeEach(() => {
7
+ global.Odac = {
8
+ Config: {request: {timeout: 5000}},
9
+ Route: {routes: {www: {}}},
10
+ Storage: {get: jest.fn(), put: jest.fn()}
11
+ }
12
+ global.__dir = '/mock'
13
+
14
+ req = {
15
+ method: 'GET',
16
+ url: '/test',
17
+ headers: {host: 'www.example.com'},
18
+ connection: {remoteAddress: '127.0.0.1'},
19
+ on: jest.fn()
20
+ }
21
+ res = {
22
+ writeHead: jest.fn(),
23
+ end: jest.fn(),
24
+ finished: false
25
+ }
26
+ request = new OdacRequest('test-id', req, res, {
27
+ setTimeout: (fn, ms) => setTimeout(fn, ms)
28
+ })
29
+ })
30
+
31
+ afterEach(() => {
32
+ delete global.Odac
33
+ delete global.__dir
34
+ })
35
+
36
+ it('should set X-ODAC-Cache header with the given TTL', () => {
37
+ request.cache(3600)
38
+
39
+ // Verify headers by printing them
40
+ request.print()
41
+ const headers = res.writeHead.mock.calls[0][1]
42
+ expect(headers['X-ODAC-Cache']).toBe(3600)
43
+ })
44
+
45
+ it('should set Cache-Control to public with correct max-age', () => {
46
+ request.cache(7200)
47
+
48
+ request.print()
49
+ const headers = res.writeHead.mock.calls[0][1]
50
+ expect(headers['Cache-Control']).toBe('public, max-age=7200')
51
+ })
52
+
53
+ it('should override a previously set Cache-Control header', () => {
54
+ request.header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
55
+ request.cache(1800)
56
+
57
+ request.print()
58
+ const headers = res.writeHead.mock.calls[0][1]
59
+ expect(headers['Cache-Control']).toBe('public, max-age=1800')
60
+ expect(headers['X-ODAC-Cache']).toBe(1800)
61
+ })
62
+
63
+ it('should throw TypeError for non-integer values', () => {
64
+ expect(() => request.cache(3.5)).toThrow(TypeError)
65
+ expect(() => request.cache('3600')).toThrow(TypeError)
66
+ expect(() => request.cache(null)).toThrow(TypeError)
67
+ expect(() => request.cache(undefined)).toThrow(TypeError)
68
+ expect(() => request.cache(NaN)).toThrow(TypeError)
69
+ expect(() => request.cache(Infinity)).toThrow(TypeError)
70
+ })
71
+
72
+ it('should throw TypeError for zero or negative values', () => {
73
+ expect(() => request.cache(0)).toThrow(TypeError)
74
+ expect(() => request.cache(-1)).toThrow(TypeError)
75
+ expect(() => request.cache(-3600)).toThrow(TypeError)
76
+ })
77
+
78
+ it('should work with small TTL values', () => {
79
+ request.cache(1)
80
+
81
+ request.print()
82
+ const headers = res.writeHead.mock.calls[0][1]
83
+ expect(headers['X-ODAC-Cache']).toBe(1)
84
+ expect(headers['Cache-Control']).toBe('public, max-age=1')
85
+ })
86
+
87
+ it('should work with large TTL values', () => {
88
+ request.cache(86400)
89
+
90
+ request.print()
91
+ const headers = res.writeHead.mock.calls[0][1]
92
+ expect(headers['X-ODAC-Cache']).toBe(86400)
93
+ expect(headers['Cache-Control']).toBe('public, max-age=86400')
94
+ })
95
+ })