@typetron/framework 0.5.3 → 0.5.4

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.
Files changed (195) hide show
  1. package/.eslintrc-old.js +208 -0
  2. package/Cache/Cache.ts +13 -0
  3. package/Cache/Stores/DatabaseStore.ts +120 -0
  4. package/Cache/Stores/FileStore.ts +69 -0
  5. package/Cache/Stores/MemoryStore.ts +71 -0
  6. package/Cache/index.ts +5 -0
  7. package/Cache/types.ts +4 -0
  8. package/Container/ClassResolver.ts +106 -0
  9. package/Container/Container.ts +144 -0
  10. package/Container/Contracts.ts +3 -0
  11. package/Container/Decorators.ts +20 -0
  12. package/Container/Metadata.ts +16 -0
  13. package/Container/Resolver.ts +27 -0
  14. package/Container/index.ts +5 -0
  15. package/Database/Clauses/Where.ts +0 -0
  16. package/Database/Connection.ts +52 -0
  17. package/Database/Decorators.ts +142 -0
  18. package/Database/Drivers/DatabaseDriver.ts +37 -0
  19. package/Database/Drivers/MySQL/Alter/index.ts +55 -0
  20. package/Database/Drivers/MySQL/ColumnDefinition.ts +16 -0
  21. package/Database/Drivers/MySQL/Create.ts +47 -0
  22. package/Database/Drivers/MySQL/MysqlDriver.ts +123 -0
  23. package/Database/Drivers/MySQL/Schema.ts +82 -0
  24. package/Database/Drivers/MySQL/index.ts +13 -0
  25. package/Database/Drivers/SQL/Schema.ts +73 -0
  26. package/Database/Drivers/SQL/Statements/Alter.ts +22 -0
  27. package/Database/Drivers/SQL/Statements/BaseStatement.ts +55 -0
  28. package/Database/Drivers/SQL/Statements/Delete.ts +20 -0
  29. package/Database/Drivers/SQL/Statements/Insert.ts +24 -0
  30. package/Database/Drivers/SQL/Statements/Select.ts +55 -0
  31. package/Database/Drivers/SQL/Statements/Update.ts +33 -0
  32. package/Database/Drivers/SQL/index.ts +8 -0
  33. package/Database/Drivers/SQLite/Create.ts +45 -0
  34. package/Database/Drivers/SQLite/Schema.ts +54 -0
  35. package/Database/Drivers/SQLite/SqliteDriver.ts +144 -0
  36. package/Database/Drivers/SQLite/index.ts +15 -0
  37. package/Database/Drivers/SchemaContract.ts +11 -0
  38. package/Database/Drivers/Statement.ts +16 -0
  39. package/Database/Drivers/index.ts +4 -0
  40. package/Database/Entity.ts +377 -0
  41. package/Database/EntityNotFoundError.ts +5 -0
  42. package/Database/EntityProxyHandler.ts +43 -0
  43. package/Database/EntityQuery.ts +197 -0
  44. package/Database/Expression.ts +3 -0
  45. package/Database/Fields.ts +816 -0
  46. package/Database/Helpers.ts +12 -0
  47. package/Database/List.ts +71 -0
  48. package/Database/Migrations/Migration.ts +10 -0
  49. package/Database/Migrations/MigrationHistory.ts +20 -0
  50. package/Database/Migrations/Migrator.ts +122 -0
  51. package/Database/Migrations/index.ts +3 -0
  52. package/Database/ORM/BaseRelationship.ts +10 -0
  53. package/Database/Query.ts +374 -0
  54. package/Database/Seeders/Seeder.ts +3 -0
  55. package/Database/Seeders/SeederManager.ts +27 -0
  56. package/Database/Seeders/index.ts +2 -0
  57. package/Database/StringExpression.ts +9 -0
  58. package/Database/Types.ts +165 -0
  59. package/Database/index.ts +23 -0
  60. package/Encryption/index.ts +51 -0
  61. package/Forms/Decorators.ts +29 -0
  62. package/Forms/Form.ts +70 -0
  63. package/Forms/FormFields.ts +36 -0
  64. package/Forms/index.ts +3 -0
  65. package/Framework/App.ts +10 -0
  66. package/Framework/Application.ts +118 -0
  67. package/Framework/Auth/Auth.ts +122 -0
  68. package/Framework/Auth/Authenticatable.ts +9 -0
  69. package/Framework/Auth/User.ts +27 -0
  70. package/Framework/Auth/index.ts +29 -0
  71. package/Framework/Config/AppConfig.ts +25 -0
  72. package/Framework/Config/AuthConfig.ts +9 -0
  73. package/Framework/Config/BaseConfig.ts +9 -0
  74. package/Framework/Config/CacheConfig.ts +38 -0
  75. package/Framework/Config/DatabaseConfig.ts +21 -0
  76. package/Framework/Config/MailConfig.ts +30 -0
  77. package/Framework/Config/index.ts +6 -0
  78. package/Framework/Middleware/AuthMiddleware.ts +31 -0
  79. package/Framework/Middleware/CorsMiddleware.ts +32 -0
  80. package/Framework/Middleware/StaticAssetsMiddleware.ts +76 -0
  81. package/Framework/Middleware/index.ts +2 -0
  82. package/Framework/Provider.ts +9 -0
  83. package/Framework/Providers/CacheProvider.ts +28 -0
  84. package/Framework/Providers/DatabaseProvider.ts +36 -0
  85. package/Framework/Providers/MailProvider.ts +31 -0
  86. package/Framework/Providers/WebsocketsProvider.ts +120 -0
  87. package/Framework/Resolvers/AuthResolver.ts +23 -0
  88. package/Framework/Resolvers/EntityResolver.ts +41 -0
  89. package/Framework/Resolvers/FormResolver.ts +37 -0
  90. package/Framework/RootDir.ts +1 -0
  91. package/Framework/index.ts +8 -0
  92. package/Frontend/Angular/index.ts +24 -0
  93. package/Frontend/Websockets/index.ts +86 -0
  94. package/Mail/MailAddress.ts +4 -0
  95. package/Mail/MailTransport.ts +6 -0
  96. package/Mail/Mailable.ts +16 -0
  97. package/Mail/Mailer.ts +27 -0
  98. package/Mail/PendingMail.ts +68 -0
  99. package/Mail/SentMessage.ts +20 -0
  100. package/Mail/Transports/MemoryTransport.ts +13 -0
  101. package/Mail/Transports/SendGridTransport.ts +95 -0
  102. package/Mail/index.ts +3 -0
  103. package/Models/Model.ts +41 -0
  104. package/Models/index.ts +54 -0
  105. package/Router/BaseController.ts +7 -0
  106. package/Router/Decorators.ts +224 -0
  107. package/Router/Guard.ts +10 -0
  108. package/Router/Http/Contracts.ts +4 -0
  109. package/Router/Http/ErrorHandler.ts +45 -0
  110. package/Router/Http/ErrorHandlerInterface.ts +6 -0
  111. package/Router/Http/Errors/HttpError.ts +15 -0
  112. package/Router/Http/Handler.ts +183 -0
  113. package/Router/Http/HttpRoute.ts +110 -0
  114. package/Router/Http/Middleware.ts +7 -0
  115. package/Router/Http/Request.ts +225 -0
  116. package/Router/Http/Response.ts +35 -0
  117. package/Router/Http/index.ts +85 -0
  118. package/Router/Metadata.ts +34 -0
  119. package/Router/Middleware.ts +16 -0
  120. package/Router/Request.ts +65 -0
  121. package/Router/Route.ts +16 -0
  122. package/Router/RouteNotFoundError.ts +5 -0
  123. package/Router/Router.ts +35 -0
  124. package/Router/Servers/index.ts +6 -0
  125. package/Router/Servers/node.ts +49 -0
  126. package/Router/Servers/uNetworking.ts +151 -0
  127. package/Router/Websockets/Handler.ts +82 -0
  128. package/Router/Websockets/Middleware.ts +7 -0
  129. package/Router/Websockets/Request.ts +3 -0
  130. package/Router/Websockets/WebsocketRoute.ts +61 -0
  131. package/Router/Websockets/index.ts +57 -0
  132. package/Router/Websockets/types.ts +23 -0
  133. package/Router/index.ts +6 -0
  134. package/Storage/File.ts +30 -0
  135. package/Storage/Image.ts +19 -0
  136. package/Storage/InvalidImage.ts +3 -0
  137. package/Storage/Storage.ts +98 -0
  138. package/Storage/index.ts +4 -0
  139. package/Storage/utils.ts +18 -0
  140. package/Support/Array.ts +184 -0
  141. package/Support/Math.ts +12 -0
  142. package/Support/Metadata.ts +31 -0
  143. package/Support/String.ts +38 -0
  144. package/Support/index.ts +19 -0
  145. package/Support/utils.ts +7 -0
  146. package/Testing/TestCase.ts +193 -0
  147. package/Validation/Rule.ts +9 -0
  148. package/Validation/RuleInterface.ts +10 -0
  149. package/Validation/Rules/Email.ts +20 -0
  150. package/Validation/Rules/FileExtension.ts +21 -0
  151. package/Validation/Rules/MaxLength.ts +17 -0
  152. package/Validation/Rules/MinLength.ts +18 -0
  153. package/Validation/Rules/Optional.ts +18 -0
  154. package/Validation/Rules/Required.ts +29 -0
  155. package/Validation/Validator.ts +7 -0
  156. package/Validation/index.ts +12 -0
  157. package/benchmark-index.js +20 -0
  158. package/benchmark.ts +47 -0
  159. package/package.json +7 -3
  160. package/tests/Cache/DatabaseStoreTest.ts +110 -0
  161. package/tests/Cache/FileStoreTest.ts +93 -0
  162. package/tests/Cache/MemoryStoreTest.ts +92 -0
  163. package/tests/Container/ContainerTest.ts +336 -0
  164. package/tests/Database/Drivers/MySQL/AlterTest.ts +100 -0
  165. package/tests/Database/Drivers/MySQL/CreateTest.ts +39 -0
  166. package/tests/Database/Drivers/MysqlDriverTest.ts +140 -0
  167. package/tests/Database/Drivers/SqliteDriverTest.ts +126 -0
  168. package/tests/Database/Entities/Article.ts +21 -0
  169. package/tests/Database/Entities/Profile.ts +21 -0
  170. package/tests/Database/Entities/Role.ts +15 -0
  171. package/tests/Database/Entities/User.ts +35 -0
  172. package/tests/Database/EntityRelationshipsTest.ts +475 -0
  173. package/tests/Database/EntityTest.ts +202 -0
  174. package/tests/Database/Migrations/RunnerTest.ts +96 -0
  175. package/tests/Database/Migrations/migrations/1.createUserTable.ts +12 -0
  176. package/tests/Database/Migrations/migrations/2.createArticlesTable.ts +12 -0
  177. package/tests/Database/QueryTest.ts +573 -0
  178. package/tests/Database/SchemaTest.ts +32 -0
  179. package/tests/Database/Seeders/RunnerTest.ts +30 -0
  180. package/tests/Database/Seeders/seeders/RandomSeeder.ts +10 -0
  181. package/tests/Database/utils.ts +16 -0
  182. package/tests/Forms/FormsTest.ts +59 -0
  183. package/tests/Framework/Middleware/StaticAssetsMiddlewareTest.ts +129 -0
  184. package/tests/Framework/Resolvers/EntityResolverTest.ts +48 -0
  185. package/tests/Framework/Router/RouterTest.ts +33 -0
  186. package/tests/Mail/MailerTest.ts +76 -0
  187. package/tests/Model/ModelTest.ts +183 -0
  188. package/tests/Router/HttpHandlerTest.ts +72 -0
  189. package/tests/Router/RequestTest.ts +77 -0
  190. package/tests/Router/WebSocketsHandlerTest.ts +51 -0
  191. package/tests/Storage/StorageTest.ts +97 -0
  192. package/tests/Support/ArrayTest.ts +167 -0
  193. package/tests/Support/StringTest.ts +18 -0
  194. package/tests/Validation/RulesTest.ts +54 -0
  195. package/types.d.ts +8 -0
@@ -0,0 +1,59 @@
1
+ import { suite, test } from '@testdeck/mocha'
2
+ import { MinLength, Required } from '../../Validation'
3
+ import { Field, Form, Rules } from '@Typetron/Forms'
4
+ import { expect } from 'chai'
5
+ import { Optional } from '@Typetron/Validation/Rules/Optional'
6
+
7
+ @suite
8
+ class FormsTest {
9
+
10
+ @test
11
+ validatesFormBasedOnValidators() {
12
+
13
+ class UserForm extends Form {
14
+ @Field()
15
+ @Rules(Required)
16
+ name: string
17
+ }
18
+
19
+ const formData = {
20
+ name: 'John'
21
+ }
22
+ const form = new UserForm()
23
+ form.fill(formData)
24
+
25
+ expect(form.valid()).to.be.equal(true)
26
+ }
27
+
28
+ @test
29
+ showsErrorWhenFormIsInvalid() {
30
+ class UserForm extends Form {
31
+ @Field()
32
+ @Rules(Required)
33
+ name: string
34
+ }
35
+
36
+ const form = new UserForm()
37
+
38
+ expect(form.valid()).to.be.equal(false)
39
+ }
40
+
41
+ @test
42
+ doesNotGiveErrorForOptionalFieldsThatHaveValidatorsAlready() {
43
+ class UserForm extends Form {
44
+ @Field()
45
+ @Rules(Optional, MinLength(10))
46
+ name?: string
47
+ }
48
+
49
+ const validForm = new UserForm()
50
+
51
+ expect(validForm.valid()).to.be.equal(true)
52
+
53
+ const invalidForm = new UserForm()
54
+ invalidForm.fill({name: ''} as object)
55
+
56
+ expect(invalidForm.valid()).to.be.equal(false)
57
+ }
58
+
59
+ }
@@ -0,0 +1,129 @@
1
+ import { suite, test } from '@testdeck/mocha'
2
+ import { Container } from '@Typetron/Container'
3
+ import { Handler, Http, Request } from '@Typetron/Router/Http'
4
+ import { expect } from 'chai'
5
+ import { Router } from '@Typetron/Router'
6
+ import { StaticAssetsMiddleware } from '@Typetron/Framework/Middleware/StaticAssetsMiddleware'
7
+ import { AppConfig } from '@Typetron/Framework'
8
+ import * as path from 'path'
9
+
10
+ @suite
11
+ class StaticAssetsMiddlewareTest {
12
+
13
+ @test
14
+ async 'resolves url to a local directory'() {
15
+ const container = new Container()
16
+
17
+ container.set<Partial<AppConfig>>(AppConfig, {
18
+ staticAssets: [
19
+ {
20
+ url: 'assets/.*',
21
+ path: path.join(__dirname, '')
22
+ }
23
+ ]
24
+ })
25
+ const router = container.get(Router)
26
+ router.middleware.http.push(StaticAssetsMiddleware)
27
+
28
+ const handler = container.get(Handler)
29
+ const request = new Request('assets/styles.css', Http.Method.GET)
30
+ const response = await handler.handle(container, request)
31
+
32
+ expect(response.headers['Content-type']).to.be.equal('text/css')
33
+ expect(String(response.body)).to.contain('color : purple')
34
+ }
35
+
36
+ @test
37
+ async 'resolves url to a static asset with the exact same name'() {
38
+ const container = new Container()
39
+
40
+ container.set<Partial<AppConfig>>(AppConfig, {
41
+ staticAssets: [
42
+ {
43
+ url: '.*',
44
+ path: path.join(__dirname, 'articles')
45
+ }
46
+ ]
47
+ })
48
+ const router = container.get(Router)
49
+ router.middleware.http.push(StaticAssetsMiddleware)
50
+
51
+ const handler = container.get(Handler)
52
+ const request = new Request('my-article.html', Http.Method.GET)
53
+ const response = await handler.handle(container, request)
54
+
55
+ expect(response.headers['Content-type']).to.be.equal('text/html')
56
+ expect(String(response.body)).to.contain('article')
57
+ }
58
+
59
+ @test
60
+ async 'resolves url to a static asset returning index file'() {
61
+ const container = new Container()
62
+
63
+ container.set<Partial<AppConfig>>(AppConfig, {
64
+ staticAssets: [
65
+ {
66
+ url: '.*',
67
+ path: path.join(__dirname, 'articles')
68
+ }
69
+ ]
70
+ })
71
+ const router = container.get(Router)
72
+ router.middleware.http.push(StaticAssetsMiddleware)
73
+
74
+ const handler = container.get(Handler)
75
+ const request = new Request('some-directory', Http.Method.GET)
76
+ const response = await handler.handle(container, request)
77
+
78
+ expect(response.headers['Content-type']).to.be.equal('text/html')
79
+ expect(String(response.body)).to.contain('index file')
80
+ }
81
+
82
+ @test
83
+ async 'resolves url to base path'() {
84
+ const container = new Container()
85
+
86
+ container.set<Partial<AppConfig>>(AppConfig, {
87
+ staticAssets: [
88
+ {
89
+ url: '.*',
90
+ path: path.join(__dirname, 'articles/some-directory'),
91
+ basePath: true
92
+ }
93
+ ]
94
+ })
95
+ const router = container.get(Router)
96
+ router.middleware.http.push(StaticAssetsMiddleware)
97
+
98
+ const handler = container.get(Handler)
99
+ const request = new Request('test', Http.Method.GET)
100
+ const response = await handler.handle(container, request)
101
+
102
+ expect(response.headers['Content-type']).to.be.equal('text/html')
103
+ expect(String(response.body)).to.contain('index file')
104
+ }
105
+
106
+ @test
107
+ async 'resolves to static resource of when having base path'() {
108
+ const container = new Container()
109
+
110
+ container.set<Partial<AppConfig>>(AppConfig, {
111
+ staticAssets: [
112
+ {
113
+ url: '.*',
114
+ path: path.join(__dirname, 'assets'),
115
+ basePath: true
116
+ }
117
+ ]
118
+ })
119
+ const router = container.get(Router)
120
+ router.middleware.http.push(StaticAssetsMiddleware)
121
+
122
+ const handler = container.get(Handler)
123
+ const request = new Request('styles.css', Http.Method.GET)
124
+ const response = await handler.handle(container, request)
125
+
126
+ expect(response.headers['Content-type']).to.be.equal('text/css')
127
+ expect(String(response.body)).to.contain('color : purple')
128
+ }
129
+ }
@@ -0,0 +1,48 @@
1
+ import { suite, test } from '@testdeck/mocha'
2
+ import { Container } from '@Typetron/Container'
3
+ import { Column, Connection, Entity, ID, Query, SqliteDriver } from '@Typetron/Database'
4
+ import { Handler } from '@Typetron/Router/Websockets'
5
+ import { AnyFunction, Type } from '@Typetron/Support'
6
+ import { Http, Request, Response } from '@Typetron/Router/Http'
7
+ import { anyOfClass, instance, mock, when } from 'ts-mockito'
8
+ import { EntityResolver } from '@Typetron/Framework/Resolvers/EntityResolver'
9
+ import { expect } from 'chai'
10
+
11
+ @suite
12
+ class EntityResolverTest {
13
+
14
+ @test
15
+ async 'resolves entity parameters'() {
16
+ const connection = mock(Connection)
17
+ Query.connection = instance(connection)
18
+ Query.connection.driver = new SqliteDriver(':memory:')
19
+ when(connection.first(anyOfClass(Query))).thenResolve({id: 2}, {id: 3})
20
+
21
+ const container = new Container()
22
+ container.resolvers.unshift(new EntityResolver(container))
23
+
24
+ class User extends Entity {
25
+ @Column()
26
+ id: ID
27
+ }
28
+
29
+ class Controller {
30
+ read(thisUser: User, thatUser: User) {
31
+ return [thisUser.id, thatUser.id]
32
+ }
33
+ }
34
+
35
+ const handler = container.get(Handler)
36
+ handler.addAction('read', Controller, 'read', [User as unknown as Type<AnyFunction>, User as unknown as Type<AnyFunction>])
37
+
38
+ const request = new Request('read', Http.Method.GET)
39
+ request.parameters = {
40
+ 0: 2,
41
+ 1: 3
42
+ }
43
+ const response: Response<[ID, ID]> = await handler.handle(container, request)
44
+
45
+ expect(response.body[0]).to.be.equal(2)
46
+ expect(response.body[1]).to.be.equal(3)
47
+ }
48
+ }
@@ -0,0 +1,33 @@
1
+ import { suite, test } from '@testdeck/mocha'
2
+ import { expect } from 'chai'
3
+ import { Action, Body, Controller, Get, Router } from '../../../Router'
4
+ import { App, Application } from '@Typetron/Framework'
5
+ import { AuthUser } from '../../../Framework/Auth'
6
+
7
+ @suite
8
+ class RouterTest {
9
+
10
+ @test
11
+ 'registers http routes and websocket actions'() {
12
+ App.instance = new Application('./tests')
13
+
14
+ @Controller()
15
+ class MyController {
16
+
17
+ @Action()
18
+ create(@AuthUser() user: string) {}
19
+
20
+ @Get()
21
+ list(@Body() content: number) {}
22
+
23
+ }
24
+
25
+ const router = App.instance.get(Router)
26
+
27
+ expect(router.routes).to.have.length(1)
28
+ expect(router.actions).to.have.length(1)
29
+ expect(router.routes[0]).to.deep.include({name: 'list'})
30
+ expect(router.actions.get('create')).to.deep.include({name: 'create'})
31
+ }
32
+
33
+ }
@@ -0,0 +1,76 @@
1
+ import { suite, test } from '@testdeck/mocha'
2
+ import { Mailable, Mailer, MemoryTransport } from '@Typetron/Mail'
3
+ import { expect } from 'chai'
4
+
5
+ class Order {
6
+ constructor(public id: number) {
7
+ }
8
+ }
9
+
10
+ class OrderShipped extends Mailable {
11
+ constructor(public order: Order) {
12
+ super()
13
+ }
14
+
15
+ content() {
16
+ return {
17
+ html: `<h2>Order #${this.order.id} shipped</h2>`,
18
+ text: `Order #${this.order.id} shipped`
19
+ }
20
+ }
21
+ }
22
+
23
+ @suite
24
+ class MailerTest {
25
+ mail = new Mailer({email: 'tester@test.com'}, new MemoryTransport())
26
+
27
+ @test
28
+ async canSendSimpleMessage() {
29
+ const sentMessage = await this.mail.to('john@example.com')
30
+ .from('from@example.com')
31
+ .replyTo('replyTo@example.com')
32
+ .subject('test')
33
+ .cc('moreUsers@example.com')
34
+ .bcc('evenMoreUsers@example.com')
35
+ .send('Order #123 shipped')
36
+
37
+ expect(sentMessage.replyTo).to.deep.equal('replyTo@example.com')
38
+ expect(sentMessage.subject).to.deep.equal('test')
39
+ expect(sentMessage.from).to.deep.equal('from@example.com')
40
+ expect(sentMessage.to).to.deep.equal('john@example.com')
41
+ expect(sentMessage.cc).to.equal('moreUsers@example.com')
42
+ expect(sentMessage.bcc).to.equal('evenMoreUsers@example.com')
43
+ expect(sentMessage.body).to.equal('Order #123 shipped')
44
+ }
45
+
46
+ @test
47
+ async canSendHtmlMessage() {
48
+ const sentMessage = await this.mail.to('john@example.com')
49
+ .cc('moreUsers@example.com')
50
+ .bcc('evenMoreUsers@example.com')
51
+ .send({html: '<h2>Order #1234 shipped</h2>', text: 'Order #1234 shipped'})
52
+
53
+ expect(sentMessage.to).to.equal('john@example.com')
54
+ expect(sentMessage.cc).to.equal('moreUsers@example.com')
55
+ expect(sentMessage.bcc).to.equal('evenMoreUsers@example.com')
56
+ expect(sentMessage.body).to.deep.equal({html: '<h2>Order #1234 shipped</h2>', text: 'Order #1234 shipped'})
57
+ }
58
+
59
+ @test
60
+ async canSendMailable() {
61
+ const order = new Order(1234)
62
+
63
+ const sentMessage = await this.mail.to('john@example.com')
64
+ .cc('moreUsers@example.com')
65
+ .bcc('evenMoreUsers@example.com')
66
+ .send(new OrderShipped(order))
67
+
68
+ expect(sentMessage.to).to.equal('john@example.com')
69
+ expect(sentMessage.cc).to.equal('moreUsers@example.com')
70
+ expect(sentMessage.bcc).to.equal('evenMoreUsers@example.com')
71
+ expect(sentMessage.body).to.deep.equal({
72
+ html: `<h2>Order #${order.id} shipped</h2>`,
73
+ text: `Order #${order.id} shipped`
74
+ })
75
+ }
76
+ }
@@ -0,0 +1,183 @@
1
+ import { expect } from 'chai'
2
+ import { suite, test } from '@testdeck/mocha'
3
+ import { Field, FieldMany, Model } from '../../Models'
4
+
5
+ @suite
6
+ class ModelTest {
7
+ @test
8
+ mapsSingleObject() {
9
+ class UserModel extends Model {
10
+ @Field()
11
+ id: number
12
+
13
+ @Field()
14
+ name: string
15
+ }
16
+
17
+ const user = {
18
+ id: 1,
19
+ name: 'John',
20
+ age: 20
21
+ }
22
+ const expectedUser = {
23
+ id: 1,
24
+ name: 'John'
25
+ }
26
+ expect(UserModel.from(user)).to.deep.equal(expectedUser)
27
+ }
28
+
29
+ // @test
30
+ // mapsSingleObjectHavingUndefinedProperties() {
31
+ // class UserModel extends Model {
32
+ // @Field()
33
+ // id: number;
34
+ //
35
+ // @Field()
36
+ // name: string;
37
+ // }
38
+ //
39
+ // const user = {
40
+ // id: 1
41
+ // };
42
+ // const expectedUser = {
43
+ // id: 1,
44
+ // name: 'John'
45
+ // };
46
+ // expect(UserModel.from(user)).to.deep.equal(expectedUser);
47
+ // }
48
+
49
+ @test
50
+ mapsListOfObject() {
51
+ class UserModel extends Model {
52
+ @Field()
53
+ id: number
54
+
55
+ @Field()
56
+ name: string
57
+ }
58
+
59
+ const user = {
60
+ id: 1,
61
+ name: 'John',
62
+ age: 20
63
+ }
64
+ const expectedUser = {
65
+ id: 1,
66
+ name: 'John'
67
+ }
68
+ expect(UserModel.from([user, user])).to.deep.equal([expectedUser, expectedUser])
69
+ }
70
+
71
+ @test
72
+ mapsDeepModelObject() {
73
+ class ProfileModel extends Model {
74
+ @Field()
75
+ address: string
76
+ }
77
+
78
+ class UserModel extends Model {
79
+ @Field()
80
+ id: number
81
+
82
+ @Field()
83
+ name: string
84
+
85
+ @Field()
86
+ profile: ProfileModel
87
+ }
88
+
89
+ const user = {
90
+ id: 1,
91
+ name: 'John',
92
+ age: 20,
93
+ profile: {
94
+ address: 'somewhere',
95
+ picture: 'avatar'
96
+ }
97
+ }
98
+ const expectedUser = {
99
+ id: 1,
100
+ name: 'John',
101
+ profile: {
102
+ address: 'somewhere'
103
+ }
104
+ }
105
+ expect(UserModel.from(user)).to.deep.equal(expectedUser)
106
+ }
107
+
108
+ @test
109
+ mapsDeepListOfObject() {
110
+ class PostModel extends Model {
111
+ @Field()
112
+ title: string
113
+ }
114
+
115
+ class UserModel extends Model {
116
+ @Field()
117
+ id: number
118
+
119
+ @Field()
120
+ name: string
121
+
122
+ @Field()
123
+ @FieldMany(PostModel)
124
+ posts: PostModel[]
125
+ }
126
+
127
+ const user = {
128
+ id: 1,
129
+ name: 'John',
130
+ age: 20,
131
+ posts: [
132
+ {
133
+ title: 'first post',
134
+ content: 'some content'
135
+ }
136
+ ]
137
+ }
138
+ const expectedUser = {
139
+ id: 1,
140
+ name: 'John',
141
+ posts: [
142
+ {
143
+ title: 'first post',
144
+ }
145
+ ]
146
+ }
147
+ expect(UserModel.from(user)).to.deep.equal(expectedUser)
148
+ }
149
+
150
+ @test
151
+ async 'Handles a promise with an object'() {
152
+ class UserModel extends Model {
153
+ @Field()
154
+ name: string
155
+ }
156
+
157
+ const user = {
158
+ name: 'John',
159
+ age: 20
160
+ }
161
+ const expectedUser = {
162
+ name: 'John'
163
+ }
164
+ expect(await UserModel.from(Promise.resolve(user))).to.deep.equal(expectedUser)
165
+ }
166
+
167
+ @test
168
+ async 'Handles a promise with a list of objects'() {
169
+ class UserModel extends Model {
170
+ @Field()
171
+ name: string
172
+ }
173
+
174
+ const user = {
175
+ name: 'John',
176
+ age: 20
177
+ }
178
+ const expectedUser = {
179
+ name: 'John'
180
+ }
181
+ expect(await UserModel.from(Promise.resolve([user, user]))).to.deep.equal([expectedUser, expectedUser])
182
+ }
183
+ }
@@ -0,0 +1,72 @@
1
+ import { suite, test } from '@testdeck/mocha'
2
+ import { Handler, Http, Request } from '../../Router/Http'
3
+ import { expect } from 'chai'
4
+ import { Container } from '@Typetron/Container'
5
+ import { Body, Controller, Get } from '../../Router'
6
+
7
+ @suite
8
+ class HttpHandlerTest {
9
+ private container: Container
10
+
11
+ async before() {
12
+ this.container = new Container()
13
+ Container.setInstance(this.container)
14
+ }
15
+
16
+ @test
17
+ 'gives error when two routes have the same path'() {
18
+
19
+ class MyController {
20
+ index() {}
21
+ }
22
+
23
+ const handler = this.container.get(Handler)
24
+ handler.addRoute('', Http.Method.GET, MyController, 'index', 'index')
25
+
26
+ expect(() => handler.addRoute('', Http.Method.POST, MyController, 'index', 'index'))
27
+ .to.not.throw(`There is already a route with the same url: [GET] ''`)
28
+ expect(() => handler.addRoute('', Http.Method.GET, MyController, 'index', 'index'))
29
+ .to.throw(`There is already a route with the same url: [GET] ''`)
30
+ }
31
+
32
+ @test
33
+ async 'returns the value from the @Body'() {
34
+ @Controller()
35
+ class MyController {
36
+ @Get('list')
37
+ list(@Body() value: string) {
38
+ return value
39
+ }
40
+
41
+ @Get('create')
42
+ create(@Body() value: string) {
43
+ return value
44
+ }
45
+ }
46
+
47
+ const router = this.container.get(Handler)
48
+
49
+ const listContent = await router.handle(this.container, new Request('list', Http.Method.GET, undefined, {}, 'test'))
50
+ expect(listContent.body).to.be.equal('test')
51
+
52
+ const createContent = await router.handle(this.container, new Request('create', Http.Method.GET))
53
+ expect(createContent.body).to.be.equal(undefined)
54
+ }
55
+
56
+ // @test
57
+ // async 'caches route urls'(done: Function) {
58
+ // class Controller {
59
+ // index() {}
60
+ // }
61
+ //
62
+ // const router = new Router()
63
+ // router.add('', Http.Method.GET, Controller, 'index', 'index')
64
+ //
65
+ // expect(router.cachedRoutes).to.be.have.length(0)
66
+ //
67
+ // const app = new Container()
68
+ // const request = new Request('', Http.Method.GET)
69
+ // await router.handle(app as Application, request)
70
+ // expect(router.findRouteIndex).to.be.called.once // ???
71
+ // }
72
+ }
@@ -0,0 +1,77 @@
1
+ import { suite, test } from '@testdeck/mocha'
2
+ import { expect } from 'chai'
3
+ import { Http, Request } from '../../Router/Http'
4
+ import { IncomingHttpHeaders } from 'http'
5
+ import { File } from '../../Storage'
6
+
7
+ @suite
8
+ class RequestTest {
9
+
10
+ private request: Request
11
+
12
+ before() {
13
+ this.request = new Request('http://example.com/test?name=value', Http.Method.GET)
14
+ this.request.setHeadersLoader(() => {
15
+ return {'content-type': 'text/html'}
16
+ })
17
+ this.request.getHeader = <T extends string | string[] | undefined>(name: keyof IncomingHttpHeaders | string): T => {
18
+ return 'text/html' as T
19
+ }
20
+ }
21
+
22
+ @test
23
+ 'uri getter should return correct uri'() {
24
+ expect(this.request.uri).to.equal('/test')
25
+ }
26
+
27
+ @test
28
+ 'method getter should return correct method'() {
29
+ expect(this.request.method).to.equal(Http.Method.GET)
30
+ }
31
+
32
+ // Assuming that the commented url getter is uncommented in your code
33
+ @test
34
+ 'url getter should return correct url'() {
35
+ expect(this.request.url).to.equal('http://example.com/test?name=value')
36
+ }
37
+
38
+ @test
39
+ 'query getter should parse and return correct query parameters'() {
40
+ expect(this.request.query).to.deep.equal({name: 'value'})
41
+ }
42
+
43
+ @test
44
+ 'cookies getter should parse and return correct cookies'() {
45
+ expect(this.request.cookies).to.deep.equal({todo: 'parse cookies'})
46
+ }
47
+
48
+ @test
49
+ 'body getter and setter should return and set body correctly'() {
50
+ this.request.body = {test: 'data'}
51
+ expect(this.request.body).to.deep.equal({test: 'data'})
52
+ }
53
+
54
+ @test
55
+ 'files getter and setter should return and set files correctly'() {
56
+ const dummyFile = { // Just a mock structure based on what you provided
57
+ originalName: 'test.txt',
58
+ directory: '/tmp',
59
+ saved: true,
60
+ path: '/tmp/test.txt'
61
+ } as File
62
+
63
+ this.request.files = {testFile: dummyFile}
64
+ expect(this.request.files).to.deep.equal({testFile: dummyFile})
65
+ }
66
+
67
+ @test
68
+ 'headers getter should return correct headers'() {
69
+ expect(this.request.headers).to.deep.equal({'content-type': 'text/html'})
70
+ }
71
+
72
+ @test
73
+ 'header value is returned'() {
74
+ expect(this.request.getHeader('random header')).to.deep.equal('text/html')
75
+ }
76
+ }
77
+