Move podcast types to own file; more WIP on role (#17)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="PodcastTypes.fs" />
|
||||
<Compile Include="SupportTypes.fs" />
|
||||
<Compile Include="DataTypes.fs" />
|
||||
<Compile Include="ViewModels.fs" />
|
||||
|
||||
@@ -0,0 +1,531 @@
|
||||
namespace MyWebLog
|
||||
|
||||
/// <summary>Valid values for the iTunes explicit rating</summary>
|
||||
[<Struct>]
|
||||
type ExplicitRating =
|
||||
| Yes
|
||||
| No
|
||||
| Clean
|
||||
|
||||
/// <summary>Parse a string into an explicit rating</summary>
|
||||
/// <param name="rating">The string representation of the rating</param>
|
||||
/// <returns>The <c>ExplicitRating</c> parsed from the string</returns>
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse rating =
|
||||
match rating with
|
||||
| "yes" -> Yes
|
||||
| "no" -> No
|
||||
| "clean" -> Clean
|
||||
| _ -> invalidArg (nameof rating) $"{rating} is not a valid explicit rating"
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with Yes -> "yes" | No -> "no" | Clean -> "clean"
|
||||
|
||||
|
||||
/// <summary>A location (specified by Podcast Index)</summary>
|
||||
type Location = {
|
||||
/// <summary>The name of the location (free-form text)</summary>
|
||||
Name: string
|
||||
|
||||
/// <summary>A geographic coordinate string (RFC 5870)</summary>
|
||||
Geo: string
|
||||
|
||||
/// <summary>An OpenStreetMap query</summary>
|
||||
Osm: string option
|
||||
}
|
||||
|
||||
open NodaTime
|
||||
|
||||
/// <summary>A chapter in a podcast episode</summary>
|
||||
type Chapter = {
|
||||
/// <summary>The start time for the chapter</summary>
|
||||
StartTime: Duration
|
||||
|
||||
/// <summary>The title for this chapter</summary>
|
||||
Title: string option
|
||||
|
||||
/// <summary>A URL for an image for this chapter</summary>
|
||||
ImageUrl: string option
|
||||
|
||||
/// <summary>A URL with information pertaining to this chapter</summary>
|
||||
Url: string option
|
||||
|
||||
/// <summary>Whether this chapter is hidden</summary>
|
||||
IsHidden: bool option
|
||||
|
||||
/// <summary>The episode end time for the chapter</summary>
|
||||
EndTime: Duration option
|
||||
|
||||
/// <summary>A location that applies to a chapter</summary>
|
||||
Location: Location option
|
||||
} with
|
||||
|
||||
/// <summary>An empty chapter</summary>
|
||||
static member Empty =
|
||||
{ StartTime = Duration.Zero
|
||||
Title = None
|
||||
ImageUrl = None
|
||||
Url = None
|
||||
IsHidden = None
|
||||
EndTime = None
|
||||
Location = None }
|
||||
|
||||
/// <summary>A group to which a podcast person can belong</summary>
|
||||
[<Struct>]
|
||||
type PersonGroup =
|
||||
| Administration
|
||||
| AudioPostProduction
|
||||
| AudioProduction
|
||||
| Cast
|
||||
| Community
|
||||
| CreativeDirection
|
||||
| Misc
|
||||
| VideoPostProduction
|
||||
| VideoProduction
|
||||
| Visuals
|
||||
| Writing
|
||||
|
||||
/// <summary>Parse a string into a group</summary>
|
||||
/// <param name="group">The string representation of the group</param>
|
||||
/// <returns>The <c>PersonGroup</c> instance parsed from the string</returns>
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse group =
|
||||
match group with
|
||||
| "Administration" -> Administration
|
||||
| "Audio Post-Production" -> AudioPostProduction
|
||||
| "Audio Production" -> AudioProduction
|
||||
| "Cast" -> Cast
|
||||
| "Community" -> Community
|
||||
| "Creative Direction" -> CreativeDirection
|
||||
| "Misc." -> Misc
|
||||
| "Video Post-Production" -> VideoPostProduction
|
||||
| "Video Production" -> VideoProduction
|
||||
| "Visuals" -> Visuals
|
||||
| "Writing" -> Writing
|
||||
| _ -> invalidArg (nameof group) $"{group} is not a valid group"
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with
|
||||
| Administration -> "Administration"
|
||||
| AudioPostProduction -> "Audio Post-Production"
|
||||
| AudioProduction -> "Audio Production"
|
||||
| Cast -> "Cast"
|
||||
| Community -> "Community"
|
||||
| CreativeDirection -> "Creative Direction"
|
||||
| Misc -> "Misc."
|
||||
| VideoPostProduction -> "Video Post-Production"
|
||||
| VideoProduction -> "Video Production"
|
||||
| Visuals -> "Visuals"
|
||||
| Writing -> "Writing"
|
||||
|
||||
|
||||
/// <summary>The role a person plays for a podcast or a podcast episode</summary>
|
||||
type PersonRole =
|
||||
| Announcer
|
||||
| AssistantCamera
|
||||
| AssistantDirector
|
||||
| AssistantEditor
|
||||
| AssociateProducer
|
||||
| AudioEditor
|
||||
| AudioEngineer
|
||||
| Author
|
||||
| BookingCoordinator
|
||||
| CameraGrip
|
||||
| CameraOperator
|
||||
| CoHost
|
||||
| Composer
|
||||
| Consultant
|
||||
| ContentManager
|
||||
| CoverArtDesigner
|
||||
| CoWriter
|
||||
| CreativeDirector
|
||||
| DevelopmentProducer
|
||||
| Director
|
||||
| EditorialDirector
|
||||
| ExecutiveProducer
|
||||
| FactChecker
|
||||
| FoleyArtist
|
||||
| GraphicDesigner
|
||||
| Guest
|
||||
| GuestHost
|
||||
| GuestWriter
|
||||
| Host
|
||||
| Intern
|
||||
| LightingDesigner
|
||||
| Logger
|
||||
| ManagingEditor
|
||||
| MarketingManager
|
||||
| MusicContributor
|
||||
| MusicProduction
|
||||
| Narrator
|
||||
| PostProductionEngineer
|
||||
| Producer
|
||||
| ProductionAssistant
|
||||
| ProductionCoordinator
|
||||
| RemoteRecordingEngineer
|
||||
| Reporter
|
||||
| Researcher
|
||||
| SalesManager
|
||||
| SalesRepresentative
|
||||
| ScriptCoordinator
|
||||
| ScriptEditor
|
||||
| SeniorProducer
|
||||
| SocialMediaManager
|
||||
| Songwriter
|
||||
| SoundDesigner
|
||||
| StoryEditor
|
||||
| StudioCoordinator
|
||||
| TechnicalDirector
|
||||
| TechnicalManager
|
||||
| ThemeMusic
|
||||
| Transcriber
|
||||
| Translator
|
||||
| VideoEditor
|
||||
| VoiceActor
|
||||
| Writer
|
||||
| WritingEditor
|
||||
|
||||
/// <summary>Parse a string into a role</summary>
|
||||
/// <param name="role">The string representation of the role</param>
|
||||
/// <returns>The <c>PersonRole</c> instance parsed from the string</returns>
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse role =
|
||||
match role with
|
||||
| "Announcer" -> Announcer
|
||||
| "Assistant Camera" -> AssistantCamera
|
||||
| "Assistant Director" -> AssistantDirector
|
||||
| "Assistant Editor" -> AssistantEditor
|
||||
| "Associate Producer" -> AssociateProducer
|
||||
| "Audio Editor" -> AudioEditor
|
||||
| "Audio Engineer" -> AudioEngineer
|
||||
| "Author" -> Author
|
||||
| "Booking Coordinator" -> BookingCoordinator
|
||||
| "Camera Grip" -> CameraGrip
|
||||
| "Camera Operator" -> CameraOperator
|
||||
| "Co-Host" -> CoHost
|
||||
| "Composer" -> Composer
|
||||
| "Consultant" -> Consultant
|
||||
| "Content Manager" -> ContentManager
|
||||
| "Cover Art Designer" -> CoverArtDesigner
|
||||
| "Co-Writer" -> CoWriter
|
||||
| "Creative Director" -> CreativeDirector
|
||||
| "Development Producer" -> DevelopmentProducer
|
||||
| "Director" -> Director
|
||||
| "Editorial Director" -> EditorialDirector
|
||||
| "Executive Producer" -> ExecutiveProducer
|
||||
| "Fact Checker" -> FactChecker
|
||||
| "Foley Artist" -> FoleyArtist
|
||||
| "Graphic Designer" -> GraphicDesigner
|
||||
| "Guest" -> Guest
|
||||
| "Guest Host" -> GuestHost
|
||||
| "Guest Writer" -> GuestWriter
|
||||
| "Host" -> Host
|
||||
| "Intern" -> Intern
|
||||
| "Lighting Designer" -> LightingDesigner
|
||||
| "Logger" -> Logger
|
||||
| "Managing Editor" -> ManagingEditor
|
||||
| "Marketing Manager" -> MarketingManager
|
||||
| "Music Contributor" -> MusicContributor
|
||||
| "Music Production" -> MusicProduction
|
||||
| "Narrator" -> Narrator
|
||||
| "Post Production Engineer" -> PostProductionEngineer
|
||||
| "Producer" -> Producer
|
||||
| "Production Assistant" -> ProductionAssistant
|
||||
| "Production Coordinator" -> ProductionCoordinator
|
||||
| "Remote Recording Engineer" -> RemoteRecordingEngineer
|
||||
| "Reporter" -> Reporter
|
||||
| "Researcher" -> Researcher
|
||||
| "Sales Manager" -> SalesManager
|
||||
| "Sales Representative" -> SalesRepresentative
|
||||
| "Script Coordinator" -> ScriptCoordinator
|
||||
| "Script Editor" -> ScriptEditor
|
||||
| "Senior Producer" -> SeniorProducer
|
||||
| "Social Media Manager" -> SocialMediaManager
|
||||
| "Songwriter" -> Songwriter
|
||||
| "Sound Designer" -> SoundDesigner
|
||||
| "Story Editor" -> StoryEditor
|
||||
| "Studio Coordinator" -> StudioCoordinator
|
||||
| "Technical Director" -> TechnicalDirector
|
||||
| "Technical Manager" -> TechnicalManager
|
||||
| "Theme Music" -> ThemeMusic
|
||||
| "Transcriber" -> Transcriber
|
||||
| "Translator" -> Translator
|
||||
| "Editor (Video)" -> VideoEditor
|
||||
| "Voice Actor" -> VoiceActor
|
||||
| "Writer" -> Writer
|
||||
| "Editor (Writing)" -> WritingEditor
|
||||
| _ -> invalidArg (nameof role) $"{role} is not a valid role"
|
||||
|
||||
/// <summary>Role / group cross-reference</summary>
|
||||
static member GroupXref =
|
||||
[ Announcer, Cast
|
||||
AssistantCamera, VideoProduction
|
||||
AssistantDirector, CreativeDirection
|
||||
AssistantEditor, VideoPostProduction
|
||||
AssociateProducer, CreativeDirection
|
||||
AudioEditor, AudioPostProduction
|
||||
AudioEngineer, AudioProduction
|
||||
Author, Writing
|
||||
BookingCoordinator, Administration
|
||||
CameraGrip, VideoProduction
|
||||
CameraOperator, VideoProduction
|
||||
CoHost, Cast
|
||||
Composer, AudioPostProduction
|
||||
ContentManager, Administration
|
||||
Consultant, Misc
|
||||
CoverArtDesigner, Visuals
|
||||
CoWriter, Writing
|
||||
CreativeDirector, CreativeDirection
|
||||
DevelopmentProducer, CreativeDirection
|
||||
Director, CreativeDirection
|
||||
EditorialDirector, Writing
|
||||
ExecutiveProducer, CreativeDirection
|
||||
FactChecker, Writing
|
||||
FoleyArtist, AudioPostProduction
|
||||
GraphicDesigner, Visuals
|
||||
Guest, Cast
|
||||
GuestHost, Cast
|
||||
GuestWriter, Writing
|
||||
Host, Cast
|
||||
Intern, Misc
|
||||
LightingDesigner, VideoProduction
|
||||
Logger, Writing
|
||||
ManagingEditor, Writing
|
||||
MarketingManager, Administration
|
||||
MusicContributor, AudioPostProduction
|
||||
MusicProduction, AudioPostProduction
|
||||
Narrator, Cast
|
||||
PostProductionEngineer, AudioProduction
|
||||
Producer, CreativeDirection
|
||||
ProductionAssistant, Administration
|
||||
ProductionCoordinator, Administration
|
||||
RemoteRecordingEngineer, AudioProduction
|
||||
Reporter, Cast
|
||||
Researcher, Writing
|
||||
SalesManager, Administration
|
||||
SalesRepresentative, Administration
|
||||
ScriptCoordinator, Writing
|
||||
ScriptEditor, Writing
|
||||
SeniorProducer, CreativeDirection
|
||||
SocialMediaManager, Community
|
||||
Songwriter, Writing
|
||||
SoundDesigner, AudioPostProduction
|
||||
StoryEditor, Writing
|
||||
StudioCoordinator, AudioProduction
|
||||
TechnicalDirector, AudioProduction
|
||||
TechnicalManager, AudioProduction
|
||||
ThemeMusic, AudioPostProduction
|
||||
Transcriber, Writing
|
||||
Translator, Writing
|
||||
VideoEditor, VideoPostProduction
|
||||
VoiceActor, Cast
|
||||
Writer, Writing
|
||||
WritingEditor, Writing ]
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with
|
||||
| Announcer -> "Announcer"
|
||||
| AssistantCamera -> "Assistant Camera"
|
||||
| AssistantDirector -> "Assistant Director"
|
||||
| AssistantEditor -> "Assistant Editor"
|
||||
| AssociateProducer -> "Associate Producer"
|
||||
| AudioEditor -> "Audio Editor"
|
||||
| AudioEngineer -> "Audio Engineer"
|
||||
| Author -> "Author"
|
||||
| BookingCoordinator -> "Booking Coordinator"
|
||||
| CameraGrip -> "Camera Grip"
|
||||
| CameraOperator -> "Camera Operator"
|
||||
| CoHost -> "Co-Host"
|
||||
| Composer -> "Composer"
|
||||
| Consultant -> "Consultant"
|
||||
| ContentManager -> "Content Manager"
|
||||
| CoverArtDesigner -> "Cover Art Designer"
|
||||
| CoWriter -> "Co-Writer"
|
||||
| CreativeDirector -> "Creative Director"
|
||||
| DevelopmentProducer -> "Development Producer"
|
||||
| Director -> "Director"
|
||||
| EditorialDirector -> "Editorial Director"
|
||||
| ExecutiveProducer -> "Executive Producer"
|
||||
| FactChecker -> "Fact Checker"
|
||||
| FoleyArtist -> "Foley Artist"
|
||||
| GraphicDesigner -> "Graphic Designer"
|
||||
| Guest -> "Guest"
|
||||
| GuestHost -> "Guest Host"
|
||||
| GuestWriter -> "Guest Writer"
|
||||
| Host -> "Host"
|
||||
| Intern -> "Intern"
|
||||
| LightingDesigner -> "Lighting Designer"
|
||||
| Logger -> "Logger"
|
||||
| ManagingEditor -> "Managing Editor"
|
||||
| MarketingManager -> "Marketing Manager"
|
||||
| MusicContributor -> "Music Contributor"
|
||||
| MusicProduction -> "Music Production"
|
||||
| Narrator -> "Narrator"
|
||||
| PostProductionEngineer -> "Post Production Engineer"
|
||||
| Producer -> "Producer"
|
||||
| ProductionAssistant -> "Production Assistant"
|
||||
| ProductionCoordinator -> "Production Coordinator"
|
||||
| RemoteRecordingEngineer -> "Remote Recording Engineer"
|
||||
| Reporter -> "Reporter"
|
||||
| Researcher -> "Researcher"
|
||||
| SalesManager -> "Sales Manager"
|
||||
| SalesRepresentative -> "Sales Representative"
|
||||
| ScriptCoordinator -> "Script Coordinator"
|
||||
| ScriptEditor -> "Script Editor"
|
||||
| SeniorProducer -> "Senior Producer"
|
||||
| SocialMediaManager -> "Social Media Manager"
|
||||
| Songwriter -> "Songwriter"
|
||||
| SoundDesigner -> "Sound Designer"
|
||||
| StoryEditor -> "Story Editor"
|
||||
| StudioCoordinator -> "Studio Coordinator"
|
||||
| TechnicalDirector -> "Technical Director"
|
||||
| TechnicalManager -> "Technical Manager"
|
||||
| ThemeMusic -> "Theme Music"
|
||||
| Transcriber -> "Transcriber"
|
||||
| Translator -> "Translator"
|
||||
| VideoEditor -> "Editor (Video)"
|
||||
| VoiceActor -> "Voice Actor"
|
||||
| Writer -> "Writer"
|
||||
| WritingEditor -> "Editor (Writing)"
|
||||
|
||||
/// <summary>Get the display name of the role</summary>
|
||||
/// <remarks>Both Video Production and Writing have an "Editor"; this is how it should be rendered in RSS feeds and
|
||||
/// in the UI</remarks>
|
||||
member this.ToDisplay() =
|
||||
match this with VideoEditor | WritingEditor -> "Editor" | _ -> string this
|
||||
|
||||
/// <summary>Get the <c>PersonGroup</c> to which this role belongs</summary>
|
||||
member this.Group =
|
||||
PersonRole.GroupXref |> List.find (fun it -> fst it = this) |> snd
|
||||
|
||||
|
||||
open NodaTime.Text
|
||||
|
||||
/// <summary>A podcast episode</summary>
|
||||
type Episode = {
|
||||
/// <summary>The URL to the media file for the episode (may be permalink)</summary>
|
||||
Media: string
|
||||
|
||||
/// <summary>The length of the media file, in bytes</summary>
|
||||
Length: int64
|
||||
|
||||
/// <summary>The duration of the episode</summary>
|
||||
Duration: Duration option
|
||||
|
||||
/// <summary>The media type of the file (overrides podcast default if present)</summary>
|
||||
MediaType: string option
|
||||
|
||||
/// <summary>The URL to the image file for this episode (overrides podcast image if present, may be permalink)</summary>
|
||||
ImageUrl: string option
|
||||
|
||||
/// <summary>A subtitle for this episode</summary>
|
||||
Subtitle: string option
|
||||
|
||||
/// <summary>This episode's explicit rating (overrides podcast rating if present)</summary>
|
||||
Explicit: ExplicitRating option
|
||||
|
||||
/// <summary>Chapters for this episode</summary>
|
||||
Chapters: Chapter list option
|
||||
|
||||
/// <summary>A link to a chapter file</summary>
|
||||
ChapterFile: string option
|
||||
|
||||
/// <summary>The MIME type for the chapter file</summary>
|
||||
ChapterType: string option
|
||||
|
||||
/// <summary>Whether the chapters have locations that should be displayed as waypoints</summary>
|
||||
ChapterWaypoints: bool option
|
||||
|
||||
/// <summary>The URL for the transcript of the episode (may be permalink)</summary>
|
||||
TranscriptUrl: string option
|
||||
|
||||
/// <summary>The MIME type of the transcript</summary>
|
||||
TranscriptType: string option
|
||||
|
||||
/// <summary>The language in which the transcript is written</summary>
|
||||
TranscriptLang: string option
|
||||
|
||||
/// <summary>If true, the transcript will be declared (in the feed) to be a captions file</summary>
|
||||
TranscriptCaptions: bool option
|
||||
|
||||
/// <summary>The season number (for serialized podcasts)</summary>
|
||||
SeasonNumber: int option
|
||||
|
||||
/// <summary>A description of the season</summary>
|
||||
SeasonDescription: string option
|
||||
|
||||
/// <summary>The episode number</summary>
|
||||
EpisodeNumber: double option
|
||||
|
||||
/// <summary>A description of the episode</summary>
|
||||
EpisodeDescription: string option
|
||||
} with
|
||||
|
||||
/// <summary>An empty episode</summary>
|
||||
static member Empty =
|
||||
{ Media = ""
|
||||
Length = 0L
|
||||
Duration = None
|
||||
MediaType = None
|
||||
ImageUrl = None
|
||||
Subtitle = None
|
||||
Explicit = None
|
||||
Chapters = None
|
||||
ChapterFile = None
|
||||
ChapterType = None
|
||||
ChapterWaypoints = None
|
||||
TranscriptUrl = None
|
||||
TranscriptType = None
|
||||
TranscriptLang = None
|
||||
TranscriptCaptions = None
|
||||
SeasonNumber = None
|
||||
SeasonDescription = None
|
||||
EpisodeNumber = None
|
||||
EpisodeDescription = None }
|
||||
|
||||
/// <summary>Format a duration for an episode</summary>
|
||||
/// <returns>A duration formatted in hours, minutes, and seconds</returns>
|
||||
member this.FormatDuration() =
|
||||
this.Duration |> Option.map (DurationPattern.CreateWithInvariantCulture("H:mm:ss").Format)
|
||||
|
||||
|
||||
/// <summary>PodcastIndex.org podcast:medium allowed values</summary>
|
||||
[<Struct>]
|
||||
type PodcastMedium =
|
||||
| Podcast
|
||||
| Music
|
||||
| Video
|
||||
| Film
|
||||
| Audiobook
|
||||
| Newsletter
|
||||
| Blog
|
||||
|
||||
/// <summary>Parse a string into a podcast medium</summary>
|
||||
/// <param name="medium">The string to be parsed</param>
|
||||
/// <returns>The <c>PodcastMedium</c> parsed from the string</returns>
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse medium =
|
||||
match medium with
|
||||
| "podcast" -> Podcast
|
||||
| "music" -> Music
|
||||
| "video" -> Video
|
||||
| "film" -> Film
|
||||
| "audiobook" -> Audiobook
|
||||
| "newsletter" -> Newsletter
|
||||
| "blog" -> Blog
|
||||
| _ -> invalidArg (nameof medium) $"{medium} is not a valid podcast medium"
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with
|
||||
| Podcast -> "podcast"
|
||||
| Music -> "music"
|
||||
| Video -> "video"
|
||||
| Film -> "film"
|
||||
| Audiobook -> "audiobook"
|
||||
| Newsletter -> "newsletter"
|
||||
| Blog -> "blog"
|
||||
|
||||
@@ -203,492 +203,6 @@ type CommentStatus =
|
||||
match this with Approved -> "Approved" | Pending -> "Pending" | Spam -> "Spam"
|
||||
|
||||
|
||||
/// <summary>Valid values for the iTunes explicit rating</summary>
|
||||
[<Struct>]
|
||||
type ExplicitRating =
|
||||
| Yes
|
||||
| No
|
||||
| Clean
|
||||
|
||||
/// <summary>Parse a string into an explicit rating</summary>
|
||||
/// <param name="rating">The string representation of the rating</param>
|
||||
/// <returns>The <c>ExplicitRating</c> parsed from the string</returns>
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse rating =
|
||||
match rating with
|
||||
| "yes" -> Yes
|
||||
| "no" -> No
|
||||
| "clean" -> Clean
|
||||
| _ -> invalidArg (nameof rating) $"{rating} is not a valid explicit rating"
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with Yes -> "yes" | No -> "no" | Clean -> "clean"
|
||||
|
||||
|
||||
/// <summary>A location (specified by Podcast Index)</summary>
|
||||
type Location = {
|
||||
/// <summary>The name of the location (free-form text)</summary>
|
||||
Name: string
|
||||
|
||||
/// <summary>A geographic coordinate string (RFC 5870)</summary>
|
||||
Geo: string
|
||||
|
||||
/// <summary>An OpenStreetMap query</summary>
|
||||
Osm: string option
|
||||
}
|
||||
|
||||
|
||||
/// <summary>A chapter in a podcast episode</summary>
|
||||
type Chapter = {
|
||||
/// <summary>The start time for the chapter</summary>
|
||||
StartTime: Duration
|
||||
|
||||
/// <summary>The title for this chapter</summary>
|
||||
Title: string option
|
||||
|
||||
/// <summary>A URL for an image for this chapter</summary>
|
||||
ImageUrl: string option
|
||||
|
||||
/// <summary>A URL with information pertaining to this chapter</summary>
|
||||
Url: string option
|
||||
|
||||
/// <summary>Whether this chapter is hidden</summary>
|
||||
IsHidden: bool option
|
||||
|
||||
/// <summary>The episode end time for the chapter</summary>
|
||||
EndTime: Duration option
|
||||
|
||||
/// <summary>A location that applies to a chapter</summary>
|
||||
Location: Location option
|
||||
} with
|
||||
|
||||
/// <summary>An empty chapter</summary>
|
||||
static member Empty =
|
||||
{ StartTime = Duration.Zero
|
||||
Title = None
|
||||
ImageUrl = None
|
||||
Url = None
|
||||
IsHidden = None
|
||||
EndTime = None
|
||||
Location = None }
|
||||
|
||||
/// <summary>A group to which a podcast person can belong</summary>
|
||||
type PersonGroup =
|
||||
| Administration
|
||||
| AudioPostProduction
|
||||
| AudioProduction
|
||||
| Cast
|
||||
| Community
|
||||
| CreativeDirection
|
||||
| Misc
|
||||
| VideoPostProduction
|
||||
| VideoProduction
|
||||
| Visuals
|
||||
| Writing
|
||||
|
||||
/// <summary>Parse a string into a group</summary>
|
||||
/// <param name="group">The string representation of the group</param>
|
||||
/// <returns>The <c>PersonGroup</c> instance parsed from the string</returns>
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse group =
|
||||
match group with
|
||||
| "Administration" -> Administration
|
||||
| "Audio Post-Production" -> AudioPostProduction
|
||||
| "Audio Production" -> AudioProduction
|
||||
| "Cast" -> Cast
|
||||
| "Community" -> Community
|
||||
| "Creative Direction" -> CreativeDirection
|
||||
| "Misc." -> Misc
|
||||
| "Video Post-Production" -> VideoPostProduction
|
||||
| "Video Production" -> VideoProduction
|
||||
| "Visuals" -> Visuals
|
||||
| "Writing" -> Writing
|
||||
| _ -> invalidArg (nameof group) $"{group} is not a valid group"
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with
|
||||
| Administration -> "Administration"
|
||||
| AudioPostProduction -> "Audio Post-Production"
|
||||
| AudioProduction -> "Audio Production"
|
||||
| Cast -> "Cast"
|
||||
| Community -> "Community"
|
||||
| CreativeDirection -> "Creative Direction"
|
||||
| Misc -> "Misc."
|
||||
| VideoPostProduction -> "Video Post-Production"
|
||||
| VideoProduction -> "Video Production"
|
||||
| Visuals -> "Visuals"
|
||||
| Writing -> "Writing"
|
||||
|
||||
|
||||
/// <summary>The role a person plays for a podcast or a podcast episode</summary>
|
||||
type PersonRole =
|
||||
| Announcer
|
||||
| AssistantCamera
|
||||
| AssistantDirector
|
||||
| AssistantEditor
|
||||
| AssociateProducer
|
||||
| AudioEditor
|
||||
| AudioEngineer
|
||||
| Author
|
||||
| BookingCoordinator
|
||||
| CameraGrip
|
||||
| CameraOperator
|
||||
| CoHost
|
||||
| Composer
|
||||
| Consultant
|
||||
| ContentManager
|
||||
| CoverArtDesigner
|
||||
| CoWriter
|
||||
| CreativeDirector
|
||||
| DevelopmentProducer
|
||||
| Director
|
||||
| EditorialDirector
|
||||
| ExecutiveProducer
|
||||
| FactChecker
|
||||
| FoleyArtist
|
||||
| GraphicDesigner
|
||||
| Guest
|
||||
| GuestHost
|
||||
| GuestWriter
|
||||
| Host
|
||||
| Intern
|
||||
| LightingDesigner
|
||||
| Logger
|
||||
| ManagingEditor
|
||||
| MarketingManager
|
||||
| MusicContributor
|
||||
| MusicProduction
|
||||
| Narrator
|
||||
| PostProductionEngineer
|
||||
| Producer
|
||||
| ProductionAssistant
|
||||
| ProductionCoordinator
|
||||
| RemoteRecordingEngineer
|
||||
| Reporter
|
||||
| Researcher
|
||||
| SalesManager
|
||||
| SalesRepresentative
|
||||
| ScriptCoordinator
|
||||
| ScriptEditor
|
||||
| SeniorProducer
|
||||
| SocialMediaManager
|
||||
| Songwriter
|
||||
| SoundDesigner
|
||||
| StoryEditor
|
||||
| StudioCoordinator
|
||||
| TechnicalDirector
|
||||
| TechnicalManager
|
||||
| ThemeMusic
|
||||
| Transcriber
|
||||
| Translator
|
||||
| VideoEditor
|
||||
| VoiceActor
|
||||
| Writer
|
||||
| WritingEditor
|
||||
|
||||
/// <summary>Parse a string into a role</summary>
|
||||
/// <param name="role">The string representation of the role</param>
|
||||
/// <returns>The <c>PersonRole</c> instance parsed from the string</returns>
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse role =
|
||||
match role with
|
||||
| "Announcer" -> Announcer
|
||||
| "Assistant Camera" -> AssistantCamera
|
||||
| "Assistant Director" -> AssistantDirector
|
||||
| "Assistant Editor" -> AssistantEditor
|
||||
| "Associate Producer" -> AssociateProducer
|
||||
| "Audio Editor" -> AudioEditor
|
||||
| "Audio Engineer" -> AudioEngineer
|
||||
| "Author" -> Author
|
||||
| "Booking Coordinator" -> BookingCoordinator
|
||||
| "Camera Grip" -> CameraGrip
|
||||
| "Camera Operator" -> CameraOperator
|
||||
| "Co-Host" -> CoHost
|
||||
| "Composer" -> Composer
|
||||
| "Consultant" -> Consultant
|
||||
| "Content Manager" -> ContentManager
|
||||
| "Cover Art Designer" -> CoverArtDesigner
|
||||
| "Co-Writer" -> CoWriter
|
||||
| "Creative Director" -> CreativeDirector
|
||||
| "Development Producer" -> DevelopmentProducer
|
||||
| "Director" -> Director
|
||||
| "Editorial Director" -> EditorialDirector
|
||||
| "Executive Producer" -> ExecutiveProducer
|
||||
| "Fact Checker" -> FactChecker
|
||||
| "Foley Artist" -> FoleyArtist
|
||||
| "Graphic Designer" -> GraphicDesigner
|
||||
| "Guest" -> Guest
|
||||
| "Guest Host" -> GuestHost
|
||||
| "Guest Writer" -> GuestWriter
|
||||
| "Host" -> Host
|
||||
| "Intern" -> Intern
|
||||
| "Lighting Designer" -> LightingDesigner
|
||||
| "Logger" -> Logger
|
||||
| "Managing Editor" -> ManagingEditor
|
||||
| "Marketing Manager" -> MarketingManager
|
||||
| "Music Contributor" -> MusicContributor
|
||||
| "Music Production" -> MusicProduction
|
||||
| "Narrator" -> Narrator
|
||||
| "Post Production Engineer" -> PostProductionEngineer
|
||||
| "Producer" -> Producer
|
||||
| "Production Assistant" -> ProductionAssistant
|
||||
| "Production Coordinator" -> ProductionCoordinator
|
||||
| "Remote Recording Engineer" -> RemoteRecordingEngineer
|
||||
| "Reporter" -> Reporter
|
||||
| "Researcher" -> Researcher
|
||||
| "Sales Manager" -> SalesManager
|
||||
| "Sales Representative" -> SalesRepresentative
|
||||
| "Script Coordinator" -> ScriptCoordinator
|
||||
| "Script Editor" -> ScriptEditor
|
||||
| "Senior Producer" -> SeniorProducer
|
||||
| "Social Media Manager" -> SocialMediaManager
|
||||
| "Songwriter" -> Songwriter
|
||||
| "Sound Designer" -> SoundDesigner
|
||||
| "Story Editor" -> StoryEditor
|
||||
| "Studio Coordinator" -> StudioCoordinator
|
||||
| "Technical Director" -> TechnicalDirector
|
||||
| "Technical Manager" -> TechnicalManager
|
||||
| "Theme Music" -> ThemeMusic
|
||||
| "Transcriber" -> Transcriber
|
||||
| "Translator" -> Translator
|
||||
| "Editor (Video)" -> VideoEditor
|
||||
| "Voice Actor" -> VoiceActor
|
||||
| "Writer" -> Writer
|
||||
| "Editor (Writing)" -> WritingEditor
|
||||
| _ -> invalidArg (nameof role) $"{role} is not a valid role"
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with
|
||||
| Announcer -> "Announcer"
|
||||
| AssistantCamera -> "Assistant Camera"
|
||||
| AssistantDirector -> "Assistant Director"
|
||||
| AssistantEditor -> "Assistant Editor"
|
||||
| AssociateProducer -> "Associate Producer"
|
||||
| AudioEditor -> "Audio Editor"
|
||||
| AudioEngineer -> "Audio Engineer"
|
||||
| Author -> "Author"
|
||||
| BookingCoordinator -> "Booking Coordinator"
|
||||
| CameraGrip -> "Camera Grip"
|
||||
| CameraOperator -> "Camera Operator"
|
||||
| CoHost -> "Co-Host"
|
||||
| Composer -> "Composer"
|
||||
| Consultant -> "Consultant"
|
||||
| ContentManager -> "Content Manager"
|
||||
| CoverArtDesigner -> "Cover Art Designer"
|
||||
| CoWriter -> "Co-Writer"
|
||||
| CreativeDirector -> "Creative Director"
|
||||
| DevelopmentProducer -> "Development Producer"
|
||||
| Director -> "Director"
|
||||
| EditorialDirector -> "Editorial Director"
|
||||
| ExecutiveProducer -> "Executive Producer"
|
||||
| FactChecker -> "Fact Checker"
|
||||
| FoleyArtist -> "Foley Artist"
|
||||
| GraphicDesigner -> "Graphic Designer"
|
||||
| Guest -> "Guest"
|
||||
| GuestHost -> "Guest Host"
|
||||
| GuestWriter -> "Guest Writer"
|
||||
| Host -> "Host"
|
||||
| Intern -> "Intern"
|
||||
| LightingDesigner -> "Lighting Designer"
|
||||
| Logger -> "Logger"
|
||||
| ManagingEditor -> "Managing Editor"
|
||||
| MarketingManager -> "Marketing Manager"
|
||||
| MusicContributor -> "Music Contributor"
|
||||
| MusicProduction -> "Music Production"
|
||||
| Narrator -> "Narrator"
|
||||
| PostProductionEngineer -> "Post Production Engineer"
|
||||
| Producer -> "Producer"
|
||||
| ProductionAssistant -> "Production Assistant"
|
||||
| ProductionCoordinator -> "Production Coordinator"
|
||||
| RemoteRecordingEngineer -> "Remote Recording Engineer"
|
||||
| Reporter -> "Reporter"
|
||||
| Researcher -> "Researcher"
|
||||
| SalesManager -> "Sales Manager"
|
||||
| SalesRepresentative -> "Sales Representative"
|
||||
| ScriptCoordinator -> "Script Coordinator"
|
||||
| ScriptEditor -> "Script Editor"
|
||||
| SeniorProducer -> "Senior Producer"
|
||||
| SocialMediaManager -> "Social Media Manager"
|
||||
| Songwriter -> "Songwriter"
|
||||
| SoundDesigner -> "Sound Designer"
|
||||
| StoryEditor -> "Story Editor"
|
||||
| StudioCoordinator -> "Studio Coordinator"
|
||||
| TechnicalDirector -> "Technical Director"
|
||||
| TechnicalManager -> "Technical Manager"
|
||||
| ThemeMusic -> "Theme Music"
|
||||
| Transcriber -> "Transcriber"
|
||||
| Translator -> "Translator"
|
||||
| VideoEditor -> "Editor (Video)"
|
||||
| VoiceActor -> "Voice Actor"
|
||||
| Writer -> "Writer"
|
||||
| WritingEditor -> "Editor (Writing)"
|
||||
|
||||
/// <summary>Get the display name of the role</summary>
|
||||
/// <remarks>Both Video Production and Writing have an "Editor"; this is how it should be rendered in RSS feeds and
|
||||
/// in the UI</remarks>
|
||||
member this.ToDisplay() =
|
||||
match this with VideoEditor | WritingEditor -> "Editor" | _ -> string this
|
||||
|
||||
/// <summary>Role / group cross-reference</summary>
|
||||
static member GroupXref =
|
||||
[ Announcer, Cast
|
||||
AssistantCamera, VideoProduction
|
||||
AssistantDirector, CreativeDirection
|
||||
AssistantEditor, VideoPostProduction
|
||||
AssociateProducer, CreativeDirection
|
||||
AudioEditor, AudioPostProduction
|
||||
AudioEngineer, AudioProduction
|
||||
Author, Writing
|
||||
BookingCoordinator, Administration
|
||||
CameraGrip, VideoProduction
|
||||
CameraOperator, VideoProduction
|
||||
CoHost, Cast
|
||||
Composer, AudioPostProduction
|
||||
ContentManager, Administration
|
||||
Consultant, Misc
|
||||
CoverArtDesigner, Visuals
|
||||
CoWriter, Writing
|
||||
CreativeDirector, CreativeDirection
|
||||
DevelopmentProducer, CreativeDirection
|
||||
Director, CreativeDirection
|
||||
EditorialDirector, Writing
|
||||
ExecutiveProducer, CreativeDirection
|
||||
FactChecker, Writing
|
||||
FoleyArtist, AudioPostProduction
|
||||
GraphicDesigner, Visuals
|
||||
Guest, Cast
|
||||
GuestHost, Cast
|
||||
GuestWriter, Writing
|
||||
Host, Cast
|
||||
Intern, Misc
|
||||
LightingDesigner, VideoProduction
|
||||
Logger, Writing
|
||||
ManagingEditor, Writing
|
||||
MarketingManager, Administration
|
||||
MusicContributor, AudioPostProduction
|
||||
MusicProduction, AudioPostProduction
|
||||
Narrator, Cast
|
||||
PostProductionEngineer, AudioProduction
|
||||
Producer, CreativeDirection
|
||||
ProductionAssistant, Administration
|
||||
ProductionCoordinator, Administration
|
||||
RemoteRecordingEngineer, AudioProduction
|
||||
Reporter, Cast
|
||||
Researcher, Writing
|
||||
SalesManager, Administration
|
||||
SalesRepresentative, Administration
|
||||
ScriptCoordinator, Writing
|
||||
ScriptEditor, Writing
|
||||
SeniorProducer, CreativeDirection
|
||||
SocialMediaManager, Community
|
||||
Songwriter, Writing
|
||||
SoundDesigner, AudioPostProduction
|
||||
StoryEditor, Writing
|
||||
StudioCoordinator, AudioProduction
|
||||
TechnicalDirector, AudioProduction
|
||||
TechnicalManager, AudioProduction
|
||||
ThemeMusic, AudioPostProduction
|
||||
Transcriber, Writing
|
||||
Translator, Writing
|
||||
VideoEditor, VideoPostProduction
|
||||
VoiceActor, Cast
|
||||
Writer, Writing
|
||||
WritingEditor, Writing ]
|
||||
|
||||
|
||||
open NodaTime.Text
|
||||
|
||||
/// <summary>A podcast episode</summary>
|
||||
type Episode = {
|
||||
/// <summary>The URL to the media file for the episode (may be permalink)</summary>
|
||||
Media: string
|
||||
|
||||
/// <summary>The length of the media file, in bytes</summary>
|
||||
Length: int64
|
||||
|
||||
/// <summary>The duration of the episode</summary>
|
||||
Duration: Duration option
|
||||
|
||||
/// <summary>The media type of the file (overrides podcast default if present)</summary>
|
||||
MediaType: string option
|
||||
|
||||
/// <summary>The URL to the image file for this episode (overrides podcast image if present, may be permalink)</summary>
|
||||
ImageUrl: string option
|
||||
|
||||
/// <summary>A subtitle for this episode</summary>
|
||||
Subtitle: string option
|
||||
|
||||
/// <summary>This episode's explicit rating (overrides podcast rating if present)</summary>
|
||||
Explicit: ExplicitRating option
|
||||
|
||||
/// <summary>Chapters for this episode</summary>
|
||||
Chapters: Chapter list option
|
||||
|
||||
/// <summary>A link to a chapter file</summary>
|
||||
ChapterFile: string option
|
||||
|
||||
/// <summary>The MIME type for the chapter file</summary>
|
||||
ChapterType: string option
|
||||
|
||||
/// <summary>Whether the chapters have locations that should be displayed as waypoints</summary>
|
||||
ChapterWaypoints: bool option
|
||||
|
||||
/// <summary>The URL for the transcript of the episode (may be permalink)</summary>
|
||||
TranscriptUrl: string option
|
||||
|
||||
/// <summary>The MIME type of the transcript</summary>
|
||||
TranscriptType: string option
|
||||
|
||||
/// <summary>The language in which the transcript is written</summary>
|
||||
TranscriptLang: string option
|
||||
|
||||
/// <summary>If true, the transcript will be declared (in the feed) to be a captions file</summary>
|
||||
TranscriptCaptions: bool option
|
||||
|
||||
/// <summary>The season number (for serialized podcasts)</summary>
|
||||
SeasonNumber: int option
|
||||
|
||||
/// <summary>A description of the season</summary>
|
||||
SeasonDescription: string option
|
||||
|
||||
/// <summary>The episode number</summary>
|
||||
EpisodeNumber: double option
|
||||
|
||||
/// <summary>A description of the episode</summary>
|
||||
EpisodeDescription: string option
|
||||
} with
|
||||
|
||||
/// <summary>An empty episode</summary>
|
||||
static member Empty =
|
||||
{ Media = ""
|
||||
Length = 0L
|
||||
Duration = None
|
||||
MediaType = None
|
||||
ImageUrl = None
|
||||
Subtitle = None
|
||||
Explicit = None
|
||||
Chapters = None
|
||||
ChapterFile = None
|
||||
ChapterType = None
|
||||
ChapterWaypoints = None
|
||||
TranscriptUrl = None
|
||||
TranscriptType = None
|
||||
TranscriptLang = None
|
||||
TranscriptCaptions = None
|
||||
SeasonNumber = None
|
||||
SeasonDescription = None
|
||||
EpisodeNumber = None
|
||||
EpisodeDescription = None }
|
||||
|
||||
/// <summary>Format a duration for an episode</summary>
|
||||
/// <returns>A duration formatted in hours, minutes, and seconds</returns>
|
||||
member this.FormatDuration() =
|
||||
this.Duration |> Option.map (DurationPattern.CreateWithInvariantCulture("H:mm:ss").Format)
|
||||
|
||||
|
||||
/// <summary>Types of markup text</summary>
|
||||
type MarkupText =
|
||||
/// <summary>Markdown text</summary>
|
||||
@@ -1069,44 +583,6 @@ type PageId =
|
||||
match this with PageId it -> it
|
||||
|
||||
|
||||
/// <summary>PodcastIndex.org podcast:medium allowed values</summary>
|
||||
[<Struct>]
|
||||
type PodcastMedium =
|
||||
| Podcast
|
||||
| Music
|
||||
| Video
|
||||
| Film
|
||||
| Audiobook
|
||||
| Newsletter
|
||||
| Blog
|
||||
|
||||
/// <summary>Parse a string into a podcast medium</summary>
|
||||
/// <param name="medium">The string to be parsed</param>
|
||||
/// <returns>The <c>PodcastMedium</c> parsed from the string</returns>
|
||||
/// <exception cref="InvalidArgumentException">If the string is not valid</exception>
|
||||
static member Parse medium =
|
||||
match medium with
|
||||
| "podcast" -> Podcast
|
||||
| "music" -> Music
|
||||
| "video" -> Video
|
||||
| "film" -> Film
|
||||
| "audiobook" -> Audiobook
|
||||
| "newsletter" -> Newsletter
|
||||
| "blog" -> Blog
|
||||
| _ -> invalidArg (nameof medium) $"{medium} is not a valid podcast medium"
|
||||
|
||||
/// <inheritdoc />
|
||||
override this.ToString() =
|
||||
match this with
|
||||
| Podcast -> "podcast"
|
||||
| Music -> "music"
|
||||
| Video -> "video"
|
||||
| Film -> "film"
|
||||
| Audiobook -> "audiobook"
|
||||
| Newsletter -> "newsletter"
|
||||
| Blog -> "blog"
|
||||
|
||||
|
||||
/// <summary>Statuses for posts</summary>
|
||||
[<Struct>]
|
||||
type PostStatus =
|
||||
|
||||
@@ -0,0 +1,654 @@
|
||||
module PodcastTypesTests
|
||||
|
||||
open System
|
||||
open Expecto
|
||||
open MyWebLog
|
||||
open NodaTime
|
||||
|
||||
/// Tests for the ExplicitRating type
|
||||
let explicitRatingTests = testList "ExplicitRating" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"yes\"" {
|
||||
Expect.equal (ExplicitRating.Parse "yes") Yes "\"yes\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"no\"" {
|
||||
Expect.equal (ExplicitRating.Parse "no") No "\"no\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"clean\"" {
|
||||
Expect.equal (ExplicitRating.Parse "clean") Clean "\"clean\" not parsed correctly"
|
||||
}
|
||||
test "fails for unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(fun () -> ignore (ExplicitRating.Parse "maybe")) "Invalid value should have raised an exception"
|
||||
}
|
||||
]
|
||||
testList "ToString" [
|
||||
test "Yes succeeds" {
|
||||
Expect.equal (string Yes) "yes" "Yes string incorrect"
|
||||
}
|
||||
test "No succeeds" {
|
||||
Expect.equal (string No) "no" "No string incorrect"
|
||||
}
|
||||
test "Clean succeeds" {
|
||||
Expect.equal (string Clean) "clean" "Clean string incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the Episode type
|
||||
let episodeTests = testList "Episode" [
|
||||
testList "FormatDuration" [
|
||||
test "succeeds when no duration is specified" {
|
||||
Expect.isNone (Episode.Empty.FormatDuration()) "A missing duration should have returned None"
|
||||
}
|
||||
test "succeeds when duration is specified" {
|
||||
Expect.equal
|
||||
({ Episode.Empty with
|
||||
Duration = Some (Duration.FromMinutes 3L + Duration.FromSeconds 13L) }.FormatDuration())
|
||||
(Some "0:03:13")
|
||||
"Duration not formatted correctly"
|
||||
}
|
||||
test "succeeds when duration is > 10 hours" {
|
||||
Expect.equal
|
||||
({ Episode.Empty with Duration = Some (Duration.FromHours 11) }.FormatDuration())
|
||||
(Some "11:00:00")
|
||||
"Duration not formatted correctly"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the PersonGroup type
|
||||
let personGroupTests = testList "PersonGroup" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"Administration\"" {
|
||||
Expect.equal (PersonGroup.Parse "Administration") Administration "Administration not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Audio Post-Production\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Audio Post-Production")
|
||||
AudioPostProduction
|
||||
"Audio Post-Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Audio Production\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Audio Production") AudioProduction "Audio Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Cast\"" {
|
||||
Expect.equal (PersonGroup.Parse "Cast") Cast "Cast not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Community\"" {
|
||||
Expect.equal (PersonGroup.Parse "Community") Community "Community not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Creative Direction\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Creative Direction") CreativeDirection "Creative Direction not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Misc.\"" {
|
||||
Expect.equal (PersonGroup.Parse "Misc.") Misc "Misc. not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Video Post-Production\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Video Post-Production")
|
||||
VideoPostProduction
|
||||
"Video Post-Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Video Production\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Video Production") VideoProduction "Video Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Visuals\"" {
|
||||
Expect.equal (PersonGroup.Parse "Visuals") Visuals "Visuals not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Writing\"" {
|
||||
Expect.equal (PersonGroup.Parse "Writing") Writing "Writing not parsed correctly"
|
||||
}
|
||||
test "fails for unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(fun () -> ignore (PersonGroup.Parse "Fan")) "Invalid value should have raised an exception"
|
||||
}
|
||||
]
|
||||
testList "ToString" [
|
||||
test "Administration succeeds" {
|
||||
Expect.equal (string Administration) "Administration" "Administration string incorrect"
|
||||
}
|
||||
test "Audio Post-Production succeeds" {
|
||||
Expect.equal (string AudioPostProduction) "Audio Post-Production" "Audio Post-Production string incorrect"
|
||||
}
|
||||
test "Audio Production succeeds" {
|
||||
Expect.equal (string AudioProduction) "Audio Production" "Audio Production string incorrect"
|
||||
}
|
||||
test "Cast succeeds" {
|
||||
Expect.equal (string Cast) "Cast" "Cast string incorrect"
|
||||
}
|
||||
test "Community succeeds" {
|
||||
Expect.equal (string Community) "Community" "Community string incorrect"
|
||||
}
|
||||
test "Creative Direction succeeds" {
|
||||
Expect.equal (string CreativeDirection) "Creative Direction" "Creative Direction string incorrect"
|
||||
}
|
||||
test "Misc succeeds" {
|
||||
Expect.equal (string Misc) "Misc." "Misc string incorrect"
|
||||
}
|
||||
test "Video Post-Production succeeds" {
|
||||
Expect.equal (string VideoPostProduction) "Video Post-Production" "Video Post-Production string incorrect"
|
||||
}
|
||||
test "Video Production succeeds" {
|
||||
Expect.equal (string VideoProduction) "Video Production" "Video Production string incorrect"
|
||||
}
|
||||
test "Visuals succeeds" {
|
||||
Expect.equal (string Visuals) "Visuals" "Visuals string incorrect"
|
||||
}
|
||||
test "Writing succeeds" {
|
||||
Expect.equal (string Writing) "Writing" "Writing string incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Unit tests for the PersonRole type
|
||||
let personRoleTests = testList "PersonRole" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"Announcer\"" {
|
||||
Expect.equal (PersonRole.Parse "Announcer") Announcer "Announcer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Assistant Camera\"" {
|
||||
Expect.equal (PersonRole.Parse "Assistant Camera") AssistantCamera "Assistant Camera not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Assistant Director\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Assistant Director") AssistantDirector "Assistant Director not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Assistant Editor\"" {
|
||||
Expect.equal (PersonRole.Parse "Assistant Editor") AssistantEditor "Assistant Editor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Associate Producer\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Associate Producer") AssociateProducer "Associate Producer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Audio Editor\"" {
|
||||
Expect.equal (PersonRole.Parse "Audio Editor") AudioEditor "Audio Editor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Audio Engineer\"" {
|
||||
Expect.equal (PersonRole.Parse "Audio Engineer") AudioEngineer "Audio Engineer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Author\"" {
|
||||
Expect.equal (PersonRole.Parse "Author") Author "Author not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Booking Coordinator\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Booking Coordinator") BookingCoordinator "Booking Coordinator not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Camera Grip\"" {
|
||||
Expect.equal (PersonRole.Parse "Camera Grip") CameraGrip "Camera Grip not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Camera Operator\"" {
|
||||
Expect.equal (PersonRole.Parse "Camera Operator") CameraOperator "Camera Operator not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Co-Host\"" {
|
||||
Expect.equal (PersonRole.Parse "Co-Host") CoHost "Co-Host not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Composer\"" {
|
||||
Expect.equal (PersonRole.Parse "Composer") Composer "Composer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Consultant\"" {
|
||||
Expect.equal (PersonRole.Parse "Consultant") Consultant "Consultant not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Content Manager\"" {
|
||||
Expect.equal (PersonRole.Parse "Content Manager") ContentManager "Content Manager not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Cover Art Designer\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Cover Art Designer") CoverArtDesigner "Cover Art Designer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Co-Writer\"" {
|
||||
Expect.equal (PersonRole.Parse "Co-Writer") CoWriter "Co-Writer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Creative Director\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Creative Director") CreativeDirector "Creative Director not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Development Producer\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Development Producer")
|
||||
DevelopmentProducer
|
||||
"Development Producer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Director\"" {
|
||||
Expect.equal (PersonRole.Parse "Director") Director "Director not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Editorial Director\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Editorial Director") EditorialDirector "Editorial Director not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Executive Producer\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Executive Producer") ExecutiveProducer "Executive Producer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Fact Checker\"" {
|
||||
Expect.equal (PersonRole.Parse "Fact Checker") FactChecker "Fact Checker not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Foley Artist\"" {
|
||||
Expect.equal (PersonRole.Parse "Foley Artist") FoleyArtist "Foley Artist not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Graphic Designer\"" {
|
||||
Expect.equal (PersonRole.Parse "Graphic Designer") GraphicDesigner "Graphic Designer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Guest\"" {
|
||||
Expect.equal (PersonRole.Parse "Guest") Guest "Guest not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Guest Host\"" {
|
||||
Expect.equal (PersonRole.Parse "Guest Host") GuestHost "Guest Host not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Guest Writer\"" {
|
||||
Expect.equal (PersonRole.Parse "Guest Writer") GuestWriter "Guest Writer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Host\"" {
|
||||
Expect.equal (PersonRole.Parse "Host") Host "Host not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Intern\"" {
|
||||
Expect.equal (PersonRole.Parse "Intern") Intern "Intern not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Lighting Designer\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Lighting Designer") LightingDesigner "Lighting Designer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Logger\"" {
|
||||
Expect.equal (PersonRole.Parse "Logger") Logger "Logger not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Managing Editor\"" {
|
||||
Expect.equal (PersonRole.Parse "Managing Editor") ManagingEditor "Managing Editor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Marketing Manager\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Marketing Manager") MarketingManager "Marketing Manager not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Music Contributor\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Music Contributor") MusicContributor "Music Contributor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Music Production\"" {
|
||||
Expect.equal (PersonRole.Parse "Music Production") MusicProduction "Music Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Narrator\"" {
|
||||
Expect.equal (PersonRole.Parse "Narrator") Narrator "Narrator not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Post Production Engineer\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Post Production Engineer")
|
||||
PostProductionEngineer
|
||||
"Post Production Engineer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Producer\"" {
|
||||
Expect.equal (PersonRole.Parse "Producer") Producer "Producer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Production Assistant\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Production Assistant")
|
||||
ProductionAssistant
|
||||
"Production Assistant not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Production Coordinator\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Production Coordinator")
|
||||
ProductionCoordinator
|
||||
"Production Coordinator not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Remote Recording Engineer\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Remote Recording Engineer")
|
||||
RemoteRecordingEngineer
|
||||
"Remote Recording Engineer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Reporter\"" {
|
||||
Expect.equal (PersonRole.Parse "Reporter") Reporter "Reporter not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Researcher\"" {
|
||||
Expect.equal (PersonRole.Parse "Researcher") Researcher "Researcher not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Sales Manager\"" {
|
||||
Expect.equal (PersonRole.Parse "Sales Manager") SalesManager "Sales Manager not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Sales Representative\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Sales Representative")
|
||||
SalesRepresentative
|
||||
"Sales Representative not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Script Coordinator\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Script Coordinator") ScriptCoordinator "Script Coordinator not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Script Editor\"" {
|
||||
Expect.equal (PersonRole.Parse "Script Editor") ScriptEditor "Script Editor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Senior Producer\"" {
|
||||
Expect.equal (PersonRole.Parse "Senior Producer") SeniorProducer "Senior Producer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Social Media Manager\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Social Media Manager") SocialMediaManager "Social Media Manager not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Songwriter\"" {
|
||||
Expect.equal (PersonRole.Parse "Songwriter") Songwriter "Songwriter not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Sound Designer\"" {
|
||||
Expect.equal (PersonRole.Parse "Sound Designer") SoundDesigner "Sound Designer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Story Editor\"" {
|
||||
Expect.equal (PersonRole.Parse "Story Editor") StoryEditor "Story Editor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Studio Coordinator\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Studio Coordinator") StudioCoordinator "Studio Coordinator not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Technical Director\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Technical Director") TechnicalDirector "Technical Director not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Technical Manager\"" {
|
||||
Expect.equal
|
||||
(PersonRole.Parse "Technical Manager") TechnicalManager "Technical Manager not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Theme Music\"" {
|
||||
Expect.equal (PersonRole.Parse "Theme Music") ThemeMusic "Theme Music not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Transcriber\"" {
|
||||
Expect.equal (PersonRole.Parse "Transcriber") Transcriber "Transcriber not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Translator\"" {
|
||||
Expect.equal (PersonRole.Parse "Translator") Translator "Translator not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Editor (Video)\"" {
|
||||
Expect.equal (PersonRole.Parse "Editor (Video)") VideoEditor "Editor (Video) not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Voice Actor\"" {
|
||||
Expect.equal (PersonRole.Parse "Voice Actor") VoiceActor "Voice Actor not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Writer\"" {
|
||||
Expect.equal (PersonRole.Parse "Writer") Writer "Writer not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Editor (Writing)\"" {
|
||||
Expect.equal (PersonRole.Parse "Editor (Writing)") WritingEditor "Editor (Writing) not parsed correctly"
|
||||
}
|
||||
test "fails for unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(fun () -> ignore (PersonRole.Parse "Gaffer")) "Invalid value should have raised an exception"
|
||||
}
|
||||
]
|
||||
testList "ToString" [
|
||||
test "succeeds for Announcer" {
|
||||
Expect.equal (string Announcer) "Announcer" "Announcer string incorrect"
|
||||
}
|
||||
test "succeeds for Assistant Camera" {
|
||||
Expect.equal (string AssistantCamera) "Assistant Camera" "Assistant Camera string incorrect"
|
||||
}
|
||||
test "succeeds for Assistant Director" {
|
||||
Expect.equal (string AssistantDirector) "Assistant Director" "Assistant Director string incorrect"
|
||||
}
|
||||
test "succeeds for Assistant Editor" {
|
||||
Expect.equal (string AssistantEditor) "Assistant Editor" "Assistant Editor string incorrect"
|
||||
}
|
||||
test "succeeds for Associate Producer" {
|
||||
Expect.equal (string AssociateProducer) "Associate Producer" "Associate Producer string incorrect"
|
||||
}
|
||||
test "succeeds for Audio Editor" {
|
||||
Expect.equal (string AudioEditor) "Audio Editor" "Audio Editor string incorrect"
|
||||
}
|
||||
test "succeeds for Audio Engineer" {
|
||||
Expect.equal (string AudioEngineer) "Audio Engineer" "Audio Engineer string incorrect"
|
||||
}
|
||||
test "succeeds for Author" {
|
||||
Expect.equal (string Author) "Author" "Author string incorrect"
|
||||
}
|
||||
test "succeeds for Booking Coordinator" {
|
||||
Expect.equal (string BookingCoordinator) "Booking Coordinator" "Booking Coordinator string incorrect"
|
||||
}
|
||||
test "succeeds for Camera Grip" {
|
||||
Expect.equal (string CameraGrip) "Camera Grip" "Camera Grip string incorrect"
|
||||
}
|
||||
test "succeeds for Camera Operator" {
|
||||
Expect.equal (string CameraOperator) "Camera Operator" "Camera Operator string incorrect"
|
||||
}
|
||||
test "succeeds for Co-Host" {
|
||||
Expect.equal (string CoHost) "Co-Host" "Co-Host string incorrect"
|
||||
}
|
||||
test "succeeds for Composer" {
|
||||
Expect.equal (string Composer) "Composer" "Composer string incorrect"
|
||||
}
|
||||
test "succeeds for Consultant" {
|
||||
Expect.equal (string Consultant) "Consultant" "Consultant string incorrect"
|
||||
}
|
||||
test "succeeds for Content Manager" {
|
||||
Expect.equal (string ContentManager) "Content Manager" "Content Manager string incorrect"
|
||||
}
|
||||
test "succeeds for Cover Art Designer" {
|
||||
Expect.equal (string CoverArtDesigner) "Cover Art Designer" "Cover Art Designer string incorrect"
|
||||
}
|
||||
test "succeeds for Co-Writer" {
|
||||
Expect.equal (string CoWriter) "Co-Writer" "Co-Writer string incorrect"
|
||||
}
|
||||
test "succeeds for Creative Director" {
|
||||
Expect.equal (string CreativeDirector) "Creative Director" "Creative Director string incorrect"
|
||||
}
|
||||
test "succeeds for Development Producer" {
|
||||
Expect.equal (string DevelopmentProducer) "Development Producer" "Development Producer string incorrect"
|
||||
}
|
||||
test "succeeds for Director" {
|
||||
Expect.equal (string Director) "Director" "Director string incorrect"
|
||||
}
|
||||
test "succeeds for Editorial Director" {
|
||||
Expect.equal (string EditorialDirector) "Editorial Director" "Editorial Director string incorrect"
|
||||
}
|
||||
test "succeeds for Executive Producer" {
|
||||
Expect.equal (string ExecutiveProducer) "Executive Producer" "Executive Producer string incorrect"
|
||||
}
|
||||
test "succeeds for Fact Checker" {
|
||||
Expect.equal (string FactChecker) "Fact Checker" "Fact Checker string incorrect"
|
||||
}
|
||||
test "succeeds for Foley Artist" {
|
||||
Expect.equal (string FoleyArtist) "Foley Artist" "Foley Artist string incorrect"
|
||||
}
|
||||
test "succeeds for Graphic Designer" {
|
||||
Expect.equal (string GraphicDesigner) "Graphic Designer" "Graphic Designer string incorrect"
|
||||
}
|
||||
test "succeeds for Guest" {
|
||||
Expect.equal (string Guest) "Guest" "Guest string incorrect"
|
||||
}
|
||||
test "succeeds for Guest Host" {
|
||||
Expect.equal (string GuestHost) "Guest Host" "Guest Host string incorrect"
|
||||
}
|
||||
test "succeeds for Guest Writer" {
|
||||
Expect.equal (string GuestWriter) "Guest Writer" "Guest Writer string incorrect"
|
||||
}
|
||||
test "succeeds for Host" {
|
||||
Expect.equal (string Host) "Host" "Host string incorrect"
|
||||
}
|
||||
test "succeeds for Intern" {
|
||||
Expect.equal (string Intern) "Intern" "Intern string incorrect"
|
||||
}
|
||||
test "succeeds for Lighting Designer" {
|
||||
Expect.equal (string LightingDesigner) "Lighting Designer" "Lighting Designer string incorrect"
|
||||
}
|
||||
test "succeeds for Logger" {
|
||||
Expect.equal (string Logger) "Logger" "Logger string incorrect"
|
||||
}
|
||||
test "succeeds for Managing Editor" {
|
||||
Expect.equal (string ManagingEditor) "Managing Editor" "Managing Editor string incorrect"
|
||||
}
|
||||
test "succeeds for Marketing Manager" {
|
||||
Expect.equal (string MarketingManager) "Marketing Manager" "Marketing Manager string incorrect"
|
||||
}
|
||||
test "succeeds for Music Contributor" {
|
||||
Expect.equal (string MusicContributor) "Music Contributor" "Music Contributor string incorrect"
|
||||
}
|
||||
test "succeeds for Music Production" {
|
||||
Expect.equal (string MusicProduction) "Music Production" "Music Production string incorrect"
|
||||
}
|
||||
test "succeeds for Narrator" {
|
||||
Expect.equal (string Narrator) "Narrator" "Narrator string incorrect"
|
||||
}
|
||||
test "succeeds for Post Production Engineer" {
|
||||
Expect.equal
|
||||
(string PostProductionEngineer) "Post Production Engineer" "Post Production Engineer string incorrect"
|
||||
}
|
||||
test "succeeds for Producer" {
|
||||
Expect.equal (string Producer) "Producer" "Producer string incorrect"
|
||||
}
|
||||
test "succeeds for Production Assistant" {
|
||||
Expect.equal (string ProductionAssistant) "Production Assistant" "Production Assistant string incorrect"
|
||||
}
|
||||
test "succeeds for Production Coordinator" {
|
||||
Expect.equal
|
||||
(string ProductionCoordinator) "Production Coordinator" "Production Coordinator string incorrect"
|
||||
}
|
||||
test "succeeds for Remote Recording Engineer" {
|
||||
Expect.equal
|
||||
(string RemoteRecordingEngineer)
|
||||
"Remote Recording Engineer"
|
||||
"Remote Recording Engineer string incorrect"
|
||||
}
|
||||
test "succeeds for Reporter" {
|
||||
Expect.equal (string Reporter) "Reporter" "Reporter string incorrect"
|
||||
}
|
||||
test "succeeds for Researcher" {
|
||||
Expect.equal (string Researcher) "Researcher" "Researcher string incorrect"
|
||||
}
|
||||
test "succeeds for Sales Manager" {
|
||||
Expect.equal (string SalesManager) "Sales Manager" "Sales Manager string incorrect"
|
||||
}
|
||||
test "succeeds for Sales Representative" {
|
||||
Expect.equal (string SalesRepresentative) "Sales Representative" "Sales Representative string incorrect"
|
||||
}
|
||||
test "succeeds for Script Coordinator" {
|
||||
Expect.equal (string ScriptCoordinator) "Script Coordinator" "Script Coordinator string incorrect"
|
||||
}
|
||||
test "succeeds for Script Editor" {
|
||||
Expect.equal (string ScriptEditor) "Script Editor" "Script Editor string incorrect"
|
||||
}
|
||||
test "succeeds for Senior Producer" {
|
||||
Expect.equal (string SeniorProducer) "Senior Producer" "Senior Producer string incorrect"
|
||||
}
|
||||
test "succeeds for Social Media Manager" {
|
||||
Expect.equal (string SocialMediaManager) "Social Media Manager" "Social Media Manager string incorrect"
|
||||
}
|
||||
test "succeeds for Songwriter" {
|
||||
Expect.equal (string Songwriter) "Songwriter" "Songwriter string incorrect"
|
||||
}
|
||||
test "succeeds for Sound Designer" {
|
||||
Expect.equal (string SoundDesigner) "Sound Designer" "Sound Designer string incorrect"
|
||||
}
|
||||
test "succeeds for Story Editor" {
|
||||
Expect.equal (string StoryEditor) "Story Editor" "Story Editor string incorrect"
|
||||
}
|
||||
test "succeeds for Studio Coordinator" {
|
||||
Expect.equal (string StudioCoordinator) "Studio Coordinator" "Studio Coordinator string incorrect"
|
||||
}
|
||||
test "succeeds for Technical Director" {
|
||||
Expect.equal (string TechnicalDirector) "Technical Director" "Technical Director string incorrect"
|
||||
}
|
||||
test "succeeds for Technical Manager" {
|
||||
Expect.equal (string TechnicalManager) "Technical Manager" "Technical Manager string incorrect"
|
||||
}
|
||||
test "succeeds for Theme Music" {
|
||||
Expect.equal (string ThemeMusic) "Theme Music" "Theme Music string incorrect"
|
||||
}
|
||||
test "succeeds for Transcriber" {
|
||||
Expect.equal (string Transcriber) "Transcriber" "Transcriber string incorrect"
|
||||
}
|
||||
test "succeeds for Translator" {
|
||||
Expect.equal (string Translator) "Translator" "Translator string incorrect"
|
||||
}
|
||||
test "succeeds for Video Editor" {
|
||||
Expect.equal (string VideoEditor) "Editor (Video)" "Video Editor string incorrect"
|
||||
}
|
||||
test "succeeds for Voice Actor" {
|
||||
Expect.equal (string VoiceActor) "Voice Actor" "Voice Editor string incorrect"
|
||||
}
|
||||
test "succeeds for Writer" {
|
||||
Expect.equal (string Writer) "Writer" "Writer string incorrect"
|
||||
}
|
||||
test "succeeds for Writing Editor" {
|
||||
Expect.equal (string WritingEditor) "Editor (Writing)" "Writing Editor string incorrect"
|
||||
}
|
||||
]
|
||||
test "Role / Group Xref has all entries" {
|
||||
Expect.hasLength PersonRole.GroupXref 63 "There should be 63 roles in the role / group xref list"
|
||||
}
|
||||
test "all values round-trip between ToString and Parse" {
|
||||
PersonRole.GroupXref
|
||||
|> List.map fst
|
||||
|> List.iter (fun it ->
|
||||
Expect.equal (it |> string |> PersonRole.Parse) it "The value did not round-trip correctly")
|
||||
}
|
||||
test "ToDisplay succeeds for all values" {
|
||||
PersonRole.GroupXref
|
||||
|> List.map fst
|
||||
|> List.iter (fun it ->
|
||||
match it with
|
||||
| VideoEditor | WritingEditor ->
|
||||
Expect.equal (it.ToDisplay()) "Editor" "The display string should be \"Editor\""
|
||||
| _ -> Expect.equal (it.ToDisplay()) (string it) "The display string should be its string value")
|
||||
}
|
||||
]
|
||||
|
||||
/// Unit tests for the PodcastMedium type
|
||||
let podcastMediumTests = testList "PodcastMedium" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"podcast\"" {
|
||||
Expect.equal (PodcastMedium.Parse "podcast") Podcast "\"podcast\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"music\"" {
|
||||
Expect.equal (PodcastMedium.Parse "music") Music "\"music\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"video\"" {
|
||||
Expect.equal (PodcastMedium.Parse "video") Video "\"video\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"film\"" {
|
||||
Expect.equal (PodcastMedium.Parse "film") Film "\"film\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"audiobook\"" {
|
||||
Expect.equal (PodcastMedium.Parse "audiobook") Audiobook "\"audiobook\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"newsletter\"" {
|
||||
Expect.equal (PodcastMedium.Parse "newsletter") Newsletter "\"newsletter\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"blog\"" {
|
||||
Expect.equal (PodcastMedium.Parse "blog") Blog "\"blog\" not parsed correctly"
|
||||
}
|
||||
test "fails for invalid type" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(fun () -> ignore (PodcastMedium.Parse "laser")) "Invalid value should have raised an exception"
|
||||
}
|
||||
]
|
||||
testList "ToString" [
|
||||
test "succeeds for Podcast" {
|
||||
Expect.equal (string Podcast) "podcast" "Podcast string incorrect"
|
||||
}
|
||||
test "succeeds for Music" {
|
||||
Expect.equal (string Music) "music" "Music string incorrect"
|
||||
}
|
||||
test "succeeds for Video" {
|
||||
Expect.equal (string Video) "video" "Video string incorrect"
|
||||
}
|
||||
test "succeeds for Film" {
|
||||
Expect.equal (string Film) "film" "Film string incorrect"
|
||||
}
|
||||
test "succeeds for Audiobook" {
|
||||
Expect.equal (string Audiobook) "audiobook" "Audiobook string incorrect"
|
||||
}
|
||||
test "succeeds for Newsletter" {
|
||||
Expect.equal (string Newsletter) "newsletter" "Newsletter string incorrect"
|
||||
}
|
||||
test "succeeds for Blog" {
|
||||
Expect.equal (string Blog) "blog" "Blog string incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// All tests for the Domain.PodcastTypes file
|
||||
let all = testList "SupportTypes" [
|
||||
explicitRatingTests
|
||||
episodeTests
|
||||
personGroupTests
|
||||
personRoleTests
|
||||
podcastMediumTests
|
||||
]
|
||||
@@ -173,57 +173,6 @@ let commentStatusTests = testList "CommentStatus" [
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the ExplicitRating type
|
||||
let explicitRatingTests = testList "ExplicitRating" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"yes\"" {
|
||||
Expect.equal (ExplicitRating.Parse "yes") Yes "\"yes\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"no\"" {
|
||||
Expect.equal (ExplicitRating.Parse "no") No "\"no\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"clean\"" {
|
||||
Expect.equal (ExplicitRating.Parse "clean") Clean "\"clean\" not parsed correctly"
|
||||
}
|
||||
test "fails for unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(fun () -> ignore (ExplicitRating.Parse "maybe")) "Invalid value should have raised an exception"
|
||||
}
|
||||
]
|
||||
testList "ToString" [
|
||||
test "Yes succeeds" {
|
||||
Expect.equal (string Yes) "yes" "Yes string incorrect"
|
||||
}
|
||||
test "No succeeds" {
|
||||
Expect.equal (string No) "no" "No string incorrect"
|
||||
}
|
||||
test "Clean succeeds" {
|
||||
Expect.equal (string Clean) "clean" "Clean string incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the Episode type
|
||||
let episodeTests = testList "Episode" [
|
||||
testList "FormatDuration" [
|
||||
test "succeeds when no duration is specified" {
|
||||
Expect.isNone (Episode.Empty.FormatDuration()) "A missing duration should have returned None"
|
||||
}
|
||||
test "succeeds when duration is specified" {
|
||||
Expect.equal
|
||||
({ Episode.Empty with
|
||||
Duration = Some (Duration.FromMinutes 3L + Duration.FromSeconds 13L) }.FormatDuration())
|
||||
(Some "0:03:13")
|
||||
"Duration not formatted correctly"
|
||||
}
|
||||
test "succeeds when duration is > 10 hours" {
|
||||
Expect.equal
|
||||
({ Episode.Empty with Duration = Some (Duration.FromHours 11) }.FormatDuration())
|
||||
(Some "11:00:00")
|
||||
"Duration not formatted correctly"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Unit tests for the MarkupText type
|
||||
let markupTextTests = testList "MarkupText" [
|
||||
@@ -684,147 +633,6 @@ let openGraphPropertiesTests = testList "OpenGraphProperties" [
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests for the PersonGroup type
|
||||
let personGroupTests = testList "PersonGroup" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"Administration\"" {
|
||||
Expect.equal (PersonGroup.Parse "Administration") Administration "Administration not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Audio Post-Production\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Audio Post-Production")
|
||||
AudioPostProduction
|
||||
"Audio Post-Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Audio Production\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Audio Production") AudioProduction "Audio Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Cast\"" {
|
||||
Expect.equal (PersonGroup.Parse "Cast") Cast "Cast not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Community\"" {
|
||||
Expect.equal (PersonGroup.Parse "Community") Community "Community not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Creative Direction\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Creative Direction") CreativeDirection "Creative Direction not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Misc.\"" {
|
||||
Expect.equal (PersonGroup.Parse "Misc.") Misc "Misc. not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Video Post-Production\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Video Post-Production")
|
||||
VideoPostProduction
|
||||
"Video Post-Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Video Production\"" {
|
||||
Expect.equal
|
||||
(PersonGroup.Parse "Video Production") VideoProduction "Video Production not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Visuals\"" {
|
||||
Expect.equal (PersonGroup.Parse "Visuals") Visuals "Visuals not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"Writing\"" {
|
||||
Expect.equal (PersonGroup.Parse "Writing") Writing "Writing not parsed correctly"
|
||||
}
|
||||
test "fails for unrecognized value" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(fun () -> ignore (PersonGroup.Parse "Fan")) "Invalid value should have raised an exception"
|
||||
}
|
||||
]
|
||||
testList "ToString" [
|
||||
test "Administration succeeds" {
|
||||
Expect.equal (string Administration) "Administration" "Administration string incorrect"
|
||||
}
|
||||
test "Audio Post-Production succeeds" {
|
||||
Expect.equal (string AudioPostProduction) "Audio Post-Production" "Audio Post-Production string incorrect"
|
||||
}
|
||||
test "Audio Production succeeds" {
|
||||
Expect.equal (string AudioProduction) "Audio Production" "Audio Production string incorrect"
|
||||
}
|
||||
test "Cast succeeds" {
|
||||
Expect.equal (string Cast) "Cast" "Cast string incorrect"
|
||||
}
|
||||
test "Community succeeds" {
|
||||
Expect.equal (string Community) "Community" "Community string incorrect"
|
||||
}
|
||||
test "Creative Direction succeeds" {
|
||||
Expect.equal (string CreativeDirection) "Creative Direction" "Creative Direction string incorrect"
|
||||
}
|
||||
test "Misc succeeds" {
|
||||
Expect.equal (string Misc) "Misc." "Misc string incorrect"
|
||||
}
|
||||
test "Video Post-Production succeeds" {
|
||||
Expect.equal (string VideoPostProduction) "Video Post-Production" "Video Post-Production string incorrect"
|
||||
}
|
||||
test "Video Production succeeds" {
|
||||
Expect.equal (string VideoProduction) "Video Production" "Video Production string incorrect"
|
||||
}
|
||||
test "Visuals succeeds" {
|
||||
Expect.equal (string Visuals) "Visuals" "Visuals string incorrect"
|
||||
}
|
||||
test "Writing succeeds" {
|
||||
Expect.equal (string Writing) "Writing" "Writing string incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Unit tests for the PodcastMedium type
|
||||
let podcastMediumTests = testList "PodcastMedium" [
|
||||
testList "Parse" [
|
||||
test "succeeds for \"podcast\"" {
|
||||
Expect.equal (PodcastMedium.Parse "podcast") Podcast "\"podcast\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"music\"" {
|
||||
Expect.equal (PodcastMedium.Parse "music") Music "\"music\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"video\"" {
|
||||
Expect.equal (PodcastMedium.Parse "video") Video "\"video\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"film\"" {
|
||||
Expect.equal (PodcastMedium.Parse "film") Film "\"film\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"audiobook\"" {
|
||||
Expect.equal (PodcastMedium.Parse "audiobook") Audiobook "\"audiobook\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"newsletter\"" {
|
||||
Expect.equal (PodcastMedium.Parse "newsletter") Newsletter "\"newsletter\" not parsed correctly"
|
||||
}
|
||||
test "succeeds for \"blog\"" {
|
||||
Expect.equal (PodcastMedium.Parse "blog") Blog "\"blog\" not parsed correctly"
|
||||
}
|
||||
test "fails for invalid type" {
|
||||
Expect.throwsT<ArgumentException>
|
||||
(fun () -> ignore (PodcastMedium.Parse "laser")) "Invalid value should have raised an exception"
|
||||
}
|
||||
]
|
||||
testList "ToString" [
|
||||
test "succeeds for Podcast" {
|
||||
Expect.equal (string Podcast) "podcast" "Podcast string incorrect"
|
||||
}
|
||||
test "succeeds for Music" {
|
||||
Expect.equal (string Music) "music" "Music string incorrect"
|
||||
}
|
||||
test "succeeds for Video" {
|
||||
Expect.equal (string Video) "video" "Video string incorrect"
|
||||
}
|
||||
test "succeeds for Film" {
|
||||
Expect.equal (string Film) "film" "Film string incorrect"
|
||||
}
|
||||
test "succeeds for Audiobook" {
|
||||
Expect.equal (string Audiobook) "audiobook" "Audiobook string incorrect"
|
||||
}
|
||||
test "succeeds for Newsletter" {
|
||||
Expect.equal (string Newsletter) "newsletter" "Newsletter string incorrect"
|
||||
}
|
||||
test "succeeds for Blog" {
|
||||
Expect.equal (string Blog) "blog" "Blog string incorrect"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Unit tests for the PostStatus type
|
||||
let postStatusTests = testList "PostStatus" [
|
||||
testList "Parse" [
|
||||
@@ -919,16 +727,12 @@ let all = testList "SupportTypes" [
|
||||
accessLevelTests
|
||||
autoHtmxTypeTests
|
||||
commentStatusTests
|
||||
explicitRatingTests
|
||||
episodeTests
|
||||
markupTextTests
|
||||
openGraphAudioTests
|
||||
openGraphImageTests
|
||||
openGraphVideoTests
|
||||
openGraphTypeTests
|
||||
openGraphPropertiesTests
|
||||
personGroupTests
|
||||
podcastMediumTests
|
||||
postStatusTests
|
||||
customFeedSourceTests
|
||||
themeAssetIdTests
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Domain\PodcastTypesTests.fs" />
|
||||
<Compile Include="Domain\SupportTypesTests.fs" />
|
||||
<Compile Include="Domain\DataTypesTests.fs" />
|
||||
<Compile Include="Domain\ViewModelsTests.fs" />
|
||||
|
||||
@@ -15,7 +15,7 @@ let allDatabases = not (rethinkOnly || sqliteOnly || postgresOnly)
|
||||
let allTests = testList "MyWebLog" [
|
||||
// Skip unit tests if running an isolated database test
|
||||
if allDatabases then
|
||||
testList "Domain" [ SupportTypesTests.all; DataTypesTests.all; ViewModelsTests.all ]
|
||||
testList "Domain" [ PodcastTypesTests.all; SupportTypesTests.all; DataTypesTests.all; ViewModelsTests.all ]
|
||||
testList "Data (Unit)" [ ConvertersTests.all; UtilsTests.all ]
|
||||
// Whether to skip integration tests
|
||||
if RethinkDbDataTests.env "UNIT_ONLY" "0" <> "1" then
|
||||
|
||||
Reference in New Issue
Block a user