SplitTest.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 VariantSchema = new Schema(
  17. {
  18. name: {
  19. type: String,
  20. minLength: MIN_VARIANT_NAME_LENGTH,
  21. maxLength: MAX_VARIANT_NAME_LENGTH,
  22. required: true,
  23. validate: {
  24. validator: function (input) {
  25. return input !== null && input !== 'default' && NAME_REGEX.test(input)
  26. },
  27. message: `invalid, cannot be 'default' and must match: ${NAME_REGEX}, got {VALUE}`,
  28. },
  29. },
  30. rolloutPercent: RolloutPercentType,
  31. rolloutStripes: [
  32. {
  33. start: RolloutPercentType,
  34. end: RolloutPercentType,
  35. },
  36. ],
  37. },
  38. { _id: false }
  39. )
  40. const VersionSchema = new Schema(
  41. {
  42. versionNumber: {
  43. type: Number,
  44. default: 1,
  45. min: [1, 'must be 1 or higher, got {VALUE}'],
  46. required: true,
  47. },
  48. phase: {
  49. type: String,
  50. default: 'alpha',
  51. enum: ['alpha', 'beta', 'release'],
  52. required: true,
  53. },
  54. active: {
  55. type: Boolean,
  56. default: true,
  57. required: true,
  58. },
  59. analyticsEnabled: {
  60. type: Boolean,
  61. default: true,
  62. required: true,
  63. },
  64. variants: [VariantSchema],
  65. createdAt: {
  66. type: Date,
  67. default: Date.now,
  68. },
  69. },
  70. { _id: false }
  71. )
  72. const SplitTestSchema = new Schema({
  73. name: {
  74. type: String,
  75. minLength: MIN_NAME_LENGTH,
  76. maxlength: MAX_NAME_LENGTH,
  77. required: true,
  78. unique: true,
  79. validate: {
  80. validator: function (input) {
  81. return input !== null && NAME_REGEX.test(input)
  82. },
  83. message: `invalid, must match: ${NAME_REGEX}`,
  84. },
  85. },
  86. versions: [VersionSchema],
  87. forbidReleasePhase: {
  88. type: Boolean,
  89. required: false,
  90. },
  91. description: {
  92. type: String,
  93. required: false,
  94. },
  95. expectedEndDate: {
  96. type: Date,
  97. required: false,
  98. },
  99. ticketUrl: {
  100. type: String,
  101. required: false,
  102. },
  103. reportsUrls: {
  104. type: [String],
  105. required: false,
  106. default: [],
  107. },
  108. winningVariant: {
  109. type: String,
  110. required: false,
  111. },
  112. archived: {
  113. type: Boolean,
  114. required: false,
  115. },
  116. })
  117. SplitTestSchema.methods.getCurrentVersion = function () {
  118. if (this.versions && this.versions.length > 0) {
  119. return _.maxBy(this.versions, 'versionNumber')
  120. } else {
  121. return undefined
  122. }
  123. }
  124. SplitTestSchema.methods.getVersion = function (versionNumber) {
  125. return _.find(this.versions || [], {
  126. versionNumber,
  127. })
  128. }
  129. module.exports = {
  130. SplitTest: mongoose.model('SplitTest', SplitTestSchema),
  131. SplitTestSchema,
  132. }