From 50f6ec4fc682ca0e6f7a3d68323984d8bcea37cd Mon Sep 17 00:00:00 2001 From: Mark McDowall Date: Sun, 3 Mar 2013 16:09:43 -0800 Subject: [PATCH] Settings wired up --- NzbDrone.Api/Settings/SettingsModule.cs | 12 +- NzbDrone.Backbone/Controller.js | 12 ++ NzbDrone.Backbone/NzbDrone.Backbone.csproj | 2 +- NzbDrone.Backbone/Routing.js | 2 + .../DownloadClientTemplate.html | 3 + .../DownloadClient/DownloadClientView.js | 29 ++++ .../Settings/Indexers/IndexersTemplate.html | 3 + .../Settings/Indexers/IndexersView.js | 29 ++++ .../Settings/Misc/MiscTemplate.html | 3 + NzbDrone.Backbone/Settings/Misc/MiscView.js | 29 ++++ .../Settings/Naming/NamingTemplate.html | 4 + .../Settings/Naming/NamingView.js | 30 ++++ .../Notifications/NotificationsTemplate.html | 3 + .../Notifications/NotificationsView.js | 29 ++++ .../Settings/Quality/QualityTemplate.html | 3 + .../Settings/Quality/QualityView.js | 29 ++++ NzbDrone.Backbone/Settings/SettingsLayout.js | 159 ++++++++++++++++++ .../Settings/SettingsLayoutTemplate.html | 19 +++ NzbDrone.Backbone/Settings/SettingsModel.js | 5 + .../Settings/System/SystemTemplate.html | 3 + .../Settings/System/SystemView.js | 29 ++++ NzbDrone.Backbone/app.js | 84 ++++----- .../ParserTests/ParserFixture.cs | 1 + 23 files changed, 480 insertions(+), 42 deletions(-) create mode 100644 NzbDrone.Backbone/Settings/DownloadClient/DownloadClientTemplate.html create mode 100644 NzbDrone.Backbone/Settings/DownloadClient/DownloadClientView.js create mode 100644 NzbDrone.Backbone/Settings/Indexers/IndexersTemplate.html create mode 100644 NzbDrone.Backbone/Settings/Indexers/IndexersView.js create mode 100644 NzbDrone.Backbone/Settings/Misc/MiscTemplate.html create mode 100644 NzbDrone.Backbone/Settings/Misc/MiscView.js create mode 100644 NzbDrone.Backbone/Settings/Naming/NamingTemplate.html create mode 100644 NzbDrone.Backbone/Settings/Naming/NamingView.js create mode 100644 NzbDrone.Backbone/Settings/Notifications/NotificationsTemplate.html create mode 100644 NzbDrone.Backbone/Settings/Notifications/NotificationsView.js create mode 100644 NzbDrone.Backbone/Settings/Quality/QualityTemplate.html create mode 100644 NzbDrone.Backbone/Settings/Quality/QualityView.js create mode 100644 NzbDrone.Backbone/Settings/SettingsLayout.js create mode 100644 NzbDrone.Backbone/Settings/SettingsLayoutTemplate.html create mode 100644 NzbDrone.Backbone/Settings/SettingsModel.js create mode 100644 NzbDrone.Backbone/Settings/System/SystemTemplate.html create mode 100644 NzbDrone.Backbone/Settings/System/SystemView.js diff --git a/NzbDrone.Api/Settings/SettingsModule.cs b/NzbDrone.Api/Settings/SettingsModule.cs index e42251347..285b27acc 100644 --- a/NzbDrone.Api/Settings/SettingsModule.cs +++ b/NzbDrone.Api/Settings/SettingsModule.cs @@ -1,4 +1,6 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using Nancy; using NzbDrone.Api.Extensions; using NzbDrone.Core.Configuration; @@ -18,8 +20,12 @@ namespace NzbDrone.Api.Settings private Response GetAllSettings() { - var settings = _configService.All(); - return settings.AsResponse(); + var collection = Request.Query.Collection; + + if(collection.HasValue && Boolean.Parse(collection.Value)) + return _configService.All().AsResponse(); + + return _configService.All().ToDictionary(c => c.Key, c => c.Value).AsResponse(); } } } \ No newline at end of file diff --git a/NzbDrone.Backbone/Controller.js b/NzbDrone.Backbone/Controller.js index 164d0233a..ec7cfbf73 100644 --- a/NzbDrone.Backbone/Controller.js +++ b/NzbDrone.Backbone/Controller.js @@ -3,6 +3,7 @@ 'Calendar/CalendarCollectionView', 'Shared/NotificationView', 'Shared/NotFoundView', 'MainMenuView', 'HeaderView', 'Series/Details/SeriesDetailsView', 'Series/EpisodeCollection'], + 'Settings/SettingsLayout'], function (app, modalRegion) { var controller = Backbone.Marionette.Controller.extend({ @@ -42,6 +43,17 @@ }); }, + settings: function(action, query) { + this.setTitle('Settings'); + + var settingsModel = new NzbDrone.Settings.SettingsModel(); + settingsModel.fetch({ + success: function(settings){ + NzbDrone.mainRegion.show(new NzbDrone.Settings.SettingsLayout(this, action, query, settings)); + } + }); + }, + notFound: function () { this.setTitle('Not Found'); NzbDrone.mainRegion.show(new NzbDrone.Shared.NotFoundView(this)); diff --git a/NzbDrone.Backbone/NzbDrone.Backbone.csproj b/NzbDrone.Backbone/NzbDrone.Backbone.csproj index 10d427023..9053e7d92 100644 --- a/NzbDrone.Backbone/NzbDrone.Backbone.csproj +++ b/NzbDrone.Backbone/NzbDrone.Backbone.csproj @@ -147,7 +147,7 @@ - + diff --git a/NzbDrone.Backbone/Routing.js b/NzbDrone.Backbone/Routing.js index 6d8820e92..b29cc4e29 100644 --- a/NzbDrone.Backbone/Routing.js +++ b/NzbDrone.Backbone/Routing.js @@ -13,6 +13,8 @@ 'upcoming': 'upcoming', 'upcoming/index': 'upcoming', 'calendar': 'calendar', + 'settings': 'settings', + 'settings/:action(/:query)': 'settings', ':whatever': 'notFound' } }); diff --git a/NzbDrone.Backbone/Settings/DownloadClient/DownloadClientTemplate.html b/NzbDrone.Backbone/Settings/DownloadClient/DownloadClientTemplate.html new file mode 100644 index 000000000..86ac9ebf4 --- /dev/null +++ b/NzbDrone.Backbone/Settings/DownloadClient/DownloadClientTemplate.html @@ -0,0 +1,3 @@ +
+ Download Client settings will go here +
\ No newline at end of file diff --git a/NzbDrone.Backbone/Settings/DownloadClient/DownloadClientView.js b/NzbDrone.Backbone/Settings/DownloadClient/DownloadClientView.js new file mode 100644 index 000000000..b062adcb2 --- /dev/null +++ b/NzbDrone.Backbone/Settings/DownloadClient/DownloadClientView.js @@ -0,0 +1,29 @@ +'use strict'; + +define([ + 'app', 'Settings/SettingsModel' + +], function () { + + NzbDrone.Settings.DownloadClient.DownloadClientView = Backbone.Marionette.ItemView.extend({ + template: 'Settings/DownloadClient/DownloadClientTemplate', + + events: { + 'click .x-save': 'save' + }, + + initialize: function (options) { + this.model = options.model; + }, + + onRender: function () { + NzbDrone.ModelBinder.bind(this.model, this.el); + }, + + + save: function () { + //Todo: Actually save the model + alert('Save pressed!'); + } + }); +}); diff --git a/NzbDrone.Backbone/Settings/Indexers/IndexersTemplate.html b/NzbDrone.Backbone/Settings/Indexers/IndexersTemplate.html new file mode 100644 index 000000000..70e312099 --- /dev/null +++ b/NzbDrone.Backbone/Settings/Indexers/IndexersTemplate.html @@ -0,0 +1,3 @@ +
+ Indexer settings will go here +
\ No newline at end of file diff --git a/NzbDrone.Backbone/Settings/Indexers/IndexersView.js b/NzbDrone.Backbone/Settings/Indexers/IndexersView.js new file mode 100644 index 000000000..18ec24ce4 --- /dev/null +++ b/NzbDrone.Backbone/Settings/Indexers/IndexersView.js @@ -0,0 +1,29 @@ +'use strict'; + +define([ + 'app', 'Settings/SettingsModel' + +], function () { + + NzbDrone.Settings.Indexers.IndexersView = Backbone.Marionette.ItemView.extend({ + template: 'Settings/Indexers/IndexersTemplate', + + events: { + 'click .x-save': 'save' + }, + + initialize: function (options) { + this.model = options.model; + }, + + onRender: function () { + NzbDrone.ModelBinder.bind(this.model, this.el); + }, + + + save: function () { + //Todo: Actually save the model + alert('Save pressed!'); + } + }); +}); diff --git a/NzbDrone.Backbone/Settings/Misc/MiscTemplate.html b/NzbDrone.Backbone/Settings/Misc/MiscTemplate.html new file mode 100644 index 000000000..d2bf14dfe --- /dev/null +++ b/NzbDrone.Backbone/Settings/Misc/MiscTemplate.html @@ -0,0 +1,3 @@ +
+ Misc settings will go here +
\ No newline at end of file diff --git a/NzbDrone.Backbone/Settings/Misc/MiscView.js b/NzbDrone.Backbone/Settings/Misc/MiscView.js new file mode 100644 index 000000000..c62deaa94 --- /dev/null +++ b/NzbDrone.Backbone/Settings/Misc/MiscView.js @@ -0,0 +1,29 @@ +'use strict'; + +define([ + 'app', 'Settings/SettingsModel' + +], function () { + + NzbDrone.Settings.Misc.MiscView = Backbone.Marionette.ItemView.extend({ + template: 'Settings/Misc/MiscTemplate', + + events: { + 'click .x-save': 'save' + }, + + initialize: function (options) { + this.model = options.model; + }, + + onRender: function () { + NzbDrone.ModelBinder.bind(this.model, this.el); + }, + + + save: function () { + //Todo: Actually save the model + alert('Save pressed!'); + } + }); +}); diff --git a/NzbDrone.Backbone/Settings/Naming/NamingTemplate.html b/NzbDrone.Backbone/Settings/Naming/NamingTemplate.html new file mode 100644 index 000000000..975a07c6c --- /dev/null +++ b/NzbDrone.Backbone/Settings/Naming/NamingTemplate.html @@ -0,0 +1,4 @@ +
+ Naming settings will go here + {{uGuid}} +
\ No newline at end of file diff --git a/NzbDrone.Backbone/Settings/Naming/NamingView.js b/NzbDrone.Backbone/Settings/Naming/NamingView.js new file mode 100644 index 000000000..24e6b7cc4 --- /dev/null +++ b/NzbDrone.Backbone/Settings/Naming/NamingView.js @@ -0,0 +1,30 @@ +'use strict'; + +define([ + 'app', 'Settings/SettingsModel' + +], function () { + + NzbDrone.Settings.Naming.NamingView = Backbone.Marionette.ItemView.extend({ + template: 'Settings/Naming/NamingTemplate', + + events: { + 'click .x-save': 'save' + }, + + initialize: function (options) { + this.model = options.model; + var test = 1; + }, + + onRender: function () { + NzbDrone.ModelBinder.bind(this.model, this.el); + }, + + + save: function () { + //Todo: Actually save the model + alert('Save pressed!'); + } + }); +}); diff --git a/NzbDrone.Backbone/Settings/Notifications/NotificationsTemplate.html b/NzbDrone.Backbone/Settings/Notifications/NotificationsTemplate.html new file mode 100644 index 000000000..49f9be984 --- /dev/null +++ b/NzbDrone.Backbone/Settings/Notifications/NotificationsTemplate.html @@ -0,0 +1,3 @@ +
+ Notification settings will go here +
\ No newline at end of file diff --git a/NzbDrone.Backbone/Settings/Notifications/NotificationsView.js b/NzbDrone.Backbone/Settings/Notifications/NotificationsView.js new file mode 100644 index 000000000..a05ace819 --- /dev/null +++ b/NzbDrone.Backbone/Settings/Notifications/NotificationsView.js @@ -0,0 +1,29 @@ +'use strict'; + +define([ + 'app', 'Settings/SettingsModel' + +], function () { + + NzbDrone.Settings.Notifications.NotificationsView = Backbone.Marionette.ItemView.extend({ + template: 'Settings/Notifications/NotificationsTemplate', + + events: { + 'click .x-save': 'save' + }, + + initialize: function (options) { + this.model = options.model; + }, + + onRender: function () { + NzbDrone.ModelBinder.bind(this.model, this.el); + }, + + + save: function () { + //Todo: Actually save the model + alert('Save pressed!'); + } + }); +}); diff --git a/NzbDrone.Backbone/Settings/Quality/QualityTemplate.html b/NzbDrone.Backbone/Settings/Quality/QualityTemplate.html new file mode 100644 index 000000000..9941dfdb1 --- /dev/null +++ b/NzbDrone.Backbone/Settings/Quality/QualityTemplate.html @@ -0,0 +1,3 @@ +
+ Quality settings will go here +
\ No newline at end of file diff --git a/NzbDrone.Backbone/Settings/Quality/QualityView.js b/NzbDrone.Backbone/Settings/Quality/QualityView.js new file mode 100644 index 000000000..8c9c0ad20 --- /dev/null +++ b/NzbDrone.Backbone/Settings/Quality/QualityView.js @@ -0,0 +1,29 @@ +'use strict'; + +define([ + 'app', 'Settings/SettingsModel' + +], function () { + + NzbDrone.Settings.Quality.QualityView = Backbone.Marionette.ItemView.extend({ + template: 'Settings/Quality/QualityTemplate', + + events: { + 'click .x-save': 'save' + }, + + initialize: function (options) { + this.model = options.model; + }, + + onRender: function () { + NzbDrone.ModelBinder.bind(this.model, this.el); + }, + + + save: function () { + //Todo: Actually save the model + alert('Save pressed!'); + } + }); +}); diff --git a/NzbDrone.Backbone/Settings/SettingsLayout.js b/NzbDrone.Backbone/Settings/SettingsLayout.js new file mode 100644 index 000000000..9b6e31236 --- /dev/null +++ b/NzbDrone.Backbone/Settings/SettingsLayout.js @@ -0,0 +1,159 @@ +define([ + 'app', + 'Quality/QualityProfileCollection', + 'Settings/Naming/NamingView', + 'Settings/Quality/QualityView', + 'Settings/Indexers/IndexersView', + 'Settings/DownloadClient/DownloadClientView', + 'Settings/Notifications/NotificationsView', + 'Settings/System/SystemView', + 'Settings/Misc/MiscView' +], + function (app, qualityProfileCollection) { + NzbDrone.Settings.SettingsLayout = Backbone.Marionette.Layout.extend({ + template: 'Settings/SettingsLayoutTemplate', + + regions: { + naming: '#naming', + quality: '#quality', + indexers: '#indexers', + downloadClient: '#download-client', + notifications: '#notifications', + system: '#system', + misc: '#misc' + }, + + ui: { + namingTab: '.x-naming-tab', + qualityTab: '.x-quality-tab', + indexersTab: '.x-indexers-tab', + downloadClientTab: '.x-download-client-tab', + notificationsTab: '.x-notifications-tab', + systemTab: '.x-system-tab', + miscTab: '.x-misc-tab' + }, + + events: { + 'click .x-naming-tab': 'showNaming', + 'click .x-quality-tab': 'showQuality', + 'click .x-indexers-tab': 'showIndexers', + 'click .x-download-client-tab': 'showDownloadClient', + 'click .x-notifications-tab': 'showNotifications', + 'click .x-system-tab': 'showSystem', + 'click .x-misc-tab': 'showMisc' + }, + + showNaming: function (e) { + if (e) { + e.preventDefault(); + } + + this.ui.namingTab.tab('show'); + NzbDrone.Router.navigate('settings/naming'); + }, + + showQuality: function (e) { + if (e) { + e.preventDefault(); + } + + this.ui.qualityTab.tab('show'); + NzbDrone.Router.navigate('settings/quality'); + }, + + showIndexers: function (e) { + if (e) { + e.preventDefault(); + } + + this.ui.indexersTab.tab('show'); + NzbDrone.Router.navigate('settings/indexers'); + }, + + showDownloadClient: function (e) { + if (e) { + e.preventDefault(); + } + + this.ui.downloadClientTab.tab('show'); + NzbDrone.Router.navigate('settings/downloadclient'); + }, + + showNotifications: function (e) { + if (e) { + e.preventDefault(); + } + + this.ui.notificationsTab.tab('show'); + NzbDrone.Router.navigate('settings/notifications'); + }, + + showSystem: function (e) { + if (e) { + e.preventDefault(); + } + + this.ui.systemTab.tab('show'); + NzbDrone.Router.navigate('settings/system'); + }, + + showMisc: function (e) { + if (e) { + e.preventDefault(); + } + + this.ui.miscTab.tab('show'); + NzbDrone.Router.navigate('settings/misc'); + }, + + initialize: function (context, action, query, settings) { + this.settings = settings; + + if (action) { + this.action = action.toLowerCase(); + } + + if (query) { + this.query = query.toLowerCase(); + } + }, + + onRender: function () { + qualityProfileCollection.fetch(); + + this.naming.show(new NzbDrone.Settings.Naming.NamingView({model: this.settings})); + this.quality.show(new NzbDrone.Settings.Quality.QualityView({model: this.settings})); + this.indexers.show(new NzbDrone.Settings.Indexers.IndexersView({model: this.settings})); + this.downloadClient.show(new NzbDrone.Settings.DownloadClient.DownloadClientView({model: this.settings})); + this.notifications.show(new NzbDrone.Settings.Notifications.NotificationsView({model: this.settings})); + this.system.show(new NzbDrone.Settings.System.SystemView({model: this.settings})); + this.misc.show(new NzbDrone.Settings.Misc.MiscView({model: this.settings})); + }, + + onShow: function () { + switch (this.action) { + case 'quality': + this.showQuality(); + break; + case 'indexers': + this.showIndexers(); + break; + case 'downloadclient': + this.showDownloadClient(); + break; + case 'notifications': + this.showNotifications(); + break; + case 'system': + this.showSystem(); + break; + case 'misc': + this.showMisc(); + break; + default: + this.showNaming(); + } + } + }); + }); + diff --git a/NzbDrone.Backbone/Settings/SettingsLayoutTemplate.html b/NzbDrone.Backbone/Settings/SettingsLayoutTemplate.html new file mode 100644 index 000000000..5f856284f --- /dev/null +++ b/NzbDrone.Backbone/Settings/SettingsLayoutTemplate.html @@ -0,0 +1,19 @@ + + +
+
Naming Settings
+
Quality Settings
+
Indexer Settings
+
Download Client Settings
+
Notification Settings
+
System Settings
+
Misc Settings
+
diff --git a/NzbDrone.Backbone/Settings/SettingsModel.js b/NzbDrone.Backbone/Settings/SettingsModel.js new file mode 100644 index 000000000..7c30696a8 --- /dev/null +++ b/NzbDrone.Backbone/Settings/SettingsModel.js @@ -0,0 +1,5 @@ +define(['app'], function (app) { + NzbDrone.Settings.SettingsModel = Backbone.Model.extend({ + url: NzbDrone.Constants.ApiRoot + '/settings' + }); +}); \ No newline at end of file diff --git a/NzbDrone.Backbone/Settings/System/SystemTemplate.html b/NzbDrone.Backbone/Settings/System/SystemTemplate.html new file mode 100644 index 000000000..8edf2eb4b --- /dev/null +++ b/NzbDrone.Backbone/Settings/System/SystemTemplate.html @@ -0,0 +1,3 @@ +
+ System settings will go here +
\ No newline at end of file diff --git a/NzbDrone.Backbone/Settings/System/SystemView.js b/NzbDrone.Backbone/Settings/System/SystemView.js new file mode 100644 index 000000000..8e3b042b6 --- /dev/null +++ b/NzbDrone.Backbone/Settings/System/SystemView.js @@ -0,0 +1,29 @@ +'use strict'; + +define([ + 'app', 'Settings/SettingsModel' + +], function () { + + NzbDrone.Settings.System.SystemView = Backbone.Marionette.ItemView.extend({ + template: 'Settings/System/SystemTemplate', + + events: { + 'click .x-save': 'save' + }, + + initialize: function (options) { + this.model = options.model; + }, + + onRender: function () { + NzbDrone.ModelBinder.bind(this.model, this.el); + }, + + + save: function () { + //Todo: Actually save the model + alert('Save pressed!'); + } + }); +}); diff --git a/NzbDrone.Backbone/app.js b/NzbDrone.Backbone/app.js index c2daa580e..f6ecd5235 100644 --- a/NzbDrone.Backbone/app.js +++ b/NzbDrone.Backbone/app.js @@ -28,55 +28,63 @@ define('app', function () { - window.NzbDrone = new Backbone.Marionette.Application(); - window.NzbDrone.Series = {}; + window.NzbDrone = new Backbone.Marionette.Application(); + window.NzbDrone.Series = {}; window.NzbDrone.Series.Index = {}; - window.NzbDrone.Series.Edit = {}; - window.NzbDrone.Series.Delete = {}; - window.NzbDrone.Series.Details = {}; - window.NzbDrone.AddSeries = {}; - window.NzbDrone.AddSeries.New = {}; - window.NzbDrone.AddSeries.Existing = {}; - window.NzbDrone.AddSeries.RootFolders = {}; - window.NzbDrone.Quality = {}; - window.NzbDrone.Shared = {}; - window.NzbDrone.Upcoming = {}; - window.NzbDrone.Calendar = {}; - - window.NzbDrone.Events = { - OpenModalDialog :'openModal', - CloseModalDialog : 'closeModal' - }, + window.NzbDrone.Series.Edit = {}; + window.NzbDrone.Series.Delete = {}; + window.NzbDrone.Series.Details = {}; + window.NzbDrone.AddSeries = {}; + window.NzbDrone.AddSeries.New = {}; + window.NzbDrone.AddSeries.Existing = {}; + window.NzbDrone.AddSeries.RootFolders = {}; + window.NzbDrone.Quality = {}; + window.NzbDrone.Shared = {}; + window.NzbDrone.Upcoming = {}; + window.NzbDrone.Calendar = {}; + window.NzbDrone.Settings = {}; + window.NzbDrone.Settings.Naming = {}; + window.NzbDrone.Settings.Quality = {}; + window.NzbDrone.Settings.Indexers = {}; + window.NzbDrone.Settings.DownloadClient = {}; + window.NzbDrone.Settings.Notifications = {}; + window.NzbDrone.Settings.System = {}; + window.NzbDrone.Settings.Misc = {}; + + window.NzbDrone.Events = { + OpenModalDialog :'openModal', + CloseModalDialog : 'closeModal' + }, - window.NzbDrone.Constants = { - ApiRoot: '/api' - }; + window.NzbDrone.Constants = { + ApiRoot: '/api' + }; - window.NzbDrone.addInitializer(function () { + window.NzbDrone.addInitializer(function () { - console.log('starting application'); + console.log('starting application'); - NzbDrone.ModelBinder = new Backbone.ModelBinder(); + NzbDrone.ModelBinder = new Backbone.ModelBinder(); - //TODO: move this out of here - Handlebars.registerHelper("formatStatus", function (status, monitored) { - if (!monitored) return ''; - if (status === 'Continuing') return ''; + //TODO: move this out of here + Handlebars.registerHelper("formatStatus", function (status, monitored) { + if (!monitored) return ''; + if (status === 'Continuing') return ''; - return ''; - }); + return ''; + }); - NzbDrone.addRegions({ - titleRegion: '#title-region', - mainRegion: '#main-region', - notificationRegion: '#notification-region', - }); + NzbDrone.addRegions({ + titleRegion: '#title-region', + mainRegion: '#main-region', + notificationRegion: '#notification-region', }); + }); - window.NzbDrone.start(); + window.NzbDrone.start(); - return NzbDrone; - }); + return NzbDrone; +}); diff --git a/NzbDrone.Core.Test/ParserTests/ParserFixture.cs b/NzbDrone.Core.Test/ParserTests/ParserFixture.cs index e82c4b3aa..55801234a 100644 --- a/NzbDrone.Core.Test/ParserTests/ParserFixture.cs +++ b/NzbDrone.Core.Test/ParserTests/ParserFixture.cs @@ -76,6 +76,7 @@ namespace NzbDrone.Core.Test.ParserTests [TestCase("S02E10 6-50 to SLC [SDTV]", "", 2, 10)] [TestCase("Franklin & Bash S02E10 6-50 to SLC [SDTV]", "Franklin & Bash", 2, 10)] [TestCase("The_Big_Bang_Theory_-_6x12_-_The_Egg_Salad_Equivalency_[HDTV-720p]", "The Big Bang Theory", 6, 12)] + [TestCase("Top_Gear.19x06.720p_HDTV_x264-FoV", "Top Gear", 19, 6)] public void ParseTitle_single(string postTitle, string title, int seasonNumber, int episodeNumber) { var result = Parser.ParseTitle(postTitle);