SplitTest.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. const mongoose = require('../infrastructure/Mongoose')
  2. const { Schema } = mongoose
  3. const _ = require('lodash')
  4. const MIN_NAME_LENGTH = 3
  5. const MAX_NAME_LENGTH = 200
  6. const MIN_VARIANT_NAME_LENGTH = 3
  7. const MAX_VARIANT_NAME_LENGTH = 255
  8. const NAME_REGEX = /^[a-z0-9-]+$/
  9. const RolloutPercentType = {
  10. type: Number,
  11. default: 0,
  12. min: [0, 'Rollout percentage must be between 0 and 100, got {VALUE}'],
  13. max: [100, 'Rollout percentage must be between 0 and 100, got {VALUE}'],
  14. required: true,
  15. }
  16. const BadgeSchema = new Schema(
  17. {
  18. tooltipText: {
  19. type: String,
  20. required: false,
  21. },
  22. url: {
  23. type: String,
  24. required: false,
  25. },
  26. },
  27. { _id: false }
  28. )
  29. const BadgeInfoSchema = new Schema(
  30. {
  31. alpha: BadgeSchema,
  32. beta: BadgeSchema,
  33. release: BadgeSchema,
  34. },
  35. { _id: false }
  36. )
  37. const VariantSchema = new Schema(
  38. {
  39. name: {
  40. type: String,
  41. minLength: MIN_VARIANT_NAME_LENGTH,
  42. maxLength: MAX_VARIANT_NAME_LENGTH,
  43. required: true,
  44. validate: {
  45. validator: function (input) {
  46. return input !== null && input !== 'default' && NAME_REGEX.test(input)
  47. },
  48. message: `invalid, cannot be 'default' and must match: ${NAME_REGEX}, got {VALUE}`,
  49. },
  50. },
  51. rolloutPercent: RolloutPercentType,
  52. rolloutStripes: [
  53. {
  54. start: RolloutPercentType,
  55. end: RolloutPercentType,
  56. },
  57. ],
  58. },
  59. { _id: false }
  60. )
  61. const VersionSchema = new Schema(
  62. {
  63. versionNumber: {
  64. type: Number,
  65. default: 1,
  66. min: [1, 'must be 1 or higher, got {VALUE}'],
  67. required: true,
  68. },
  69. phase: {
  70. type: String,
  71. default: 'alpha',
  72. enum: ['alpha', 'beta', 'release'],
  73. required: true,
  74. },
  75. active: {
  76. type: Boolean,
  77. default: true,
  78. required: true,
  79. },
  80. analyticsEnabled: {
  81. type: Boolean,
  82. default: true,
  83. required: true,
  84. },
  85. variants: [VariantSchema],
  86. createdAt: {
  87. type: Date,
  88. default: Date.now,
  89. },
  90. },
  91. { _id: false }
  92. )
  93. const SplitTestSchema = new Schema({
  94. name: {
  95. type: String,
  96. minLength: MIN_NAME_LENGTH,
  97. maxlength: MAX_NAME_LENGTH,
  98. required: true,
  99. unique: true,
  100. validate: {
  101. validator: function (input) {
  102. return input !== null && NAME_REGEX.test(input)
  103. },
  104. message: `invalid, must match: ${NAME_REGEX}`,
  105. },
  106. },
  107. versions: [VersionSchema],
  108. forbidReleasePhase: {
  109. type: Boolean,
  110. required: false,
  111. },
  112. description: {
  113. type: String,
  114. required: false,
  115. },
  116. expectedEndDate: {
  117. type: Date,
  118. required: false,
  119. },
  120. ticketUrl: {
  121. type: String,
  122. required: false,
  123. },
  124. reportsUrls: {
  125. type: [String],
  126. required: false,
  127. default: [],
  128. },
  129. winningVariant: {
  130. type: String,
  131. required: false,
  132. },
  133. archived: {
  134. type: Boolean,
  135. required: false,
  136. },
  137. badgeInfo: {
  138. type: BadgeInfoSchema,
  139. required: false,
  140. },
  141. })
  142. SplitTestSchema.methods.getCurrentVersion = function () {
  143. if (this.versions && this.versions.length > 0) {
  144. return _.maxBy(this.versions, 'versionNumber')
  145. } else {
  146. return undefined
  147. }
  148. }
  149. SplitTestSchema.methods.getVersion = function (versionNumber) {
  150. return _.find(this.versions || [], {
  151. versionNumber,
  152. })
  153. }
  154. module.exports = {
  155. SplitTest: mongoose.model('SplitTest', SplitTestSchema),
  156. SplitTestSchema,
  157. }