diff --git a/sources/advertisements/VASTParser.swift b/sources/advertisements/VASTParser.swift index d464326..8bebdb9 100644 --- a/sources/advertisements/VASTParser.swift +++ b/sources/advertisements/VASTParser.swift @@ -137,11 +137,13 @@ enum VASTParser { delegate.didStartElement = .some { (name, attr) -> Void in if let skipOffset = attr["skipoffset"] { if skipOffset.contains("%") { - guard let value = Int(skipOffset.replacingOccurrences(of: "%", with: "")) else { return } - inlineContext.skipOffset = .percentage(value) + if let value = Int(skipOffset.replacingOccurrences(of: "%", with: "")) { + inlineContext.skipOffset = .percentage(value) + } } else if skipOffset.contains(":") { - guard let value = parseTime(from: skipOffset) else { return } - inlineContext.skipOffset = .time(value) + if let value = VASTTime(with: skipOffset)?.seconds { + inlineContext.skipOffset = .time(Double(value)) + } } } @@ -505,19 +507,60 @@ enum VASTParser { return delegateStack } - static func parseTime(from string: String) -> Double? { - let components = string.components(separatedBy: ":") - guard components.count == 3 else { return nil } - return components - .compactMap(Double.init) - .enumerated() - .map { - let multipliers: [Double] = [3600, 60, 1] - return $0.element * multipliers[$0.offset] + struct VASTTime { + enum Time { + case hours([String]) + case minutes([String]) + case seconds([String]) + + private var maxValue: Int { + switch self { + case .hours: return 99 + case .minutes, .seconds: return 59 + } + } + private var multiplier: Int { + switch self { + case .hours: return 3600 + case .minutes: return 60 + case .seconds: return 1 + } + } + private var index: Int { + switch self { + case .hours: return 0 + case .minutes: return 1 + case .seconds: return 2 + } + } + private var stringTime: String { + switch self { + case .hours(let value): return value[self.index] + case .minutes(let value): return value[self.index] + case .seconds(let value): return value[self.index] + } + } + + var resultInSeconds: Int? { + guard let roundedSeconds = Double(self.stringTime)?.rounded() else { return nil } + let result = Int(roundedSeconds) + guard result <= maxValue else { return nil } + return result * multiplier } - .reduce(0.0, +) + + } + + let seconds: Int + + init?(with time: String) { + let components = time.components(separatedBy: ":") + guard components.count == 3, + let hours = Time.hours(components).resultInSeconds, + let minutes = Time.minutes(components).resultInSeconds, + let seconds = Time.seconds(components).resultInSeconds else { return nil } + self.seconds = hours + minutes + seconds + } } - //swiftlint:disable line_length //swiftlint:enable function_body_length diff --git a/sources/advertisements/VASTParserTests.swift b/sources/advertisements/VASTParserTests.swift index 99adccf..bc83e14 100644 --- a/sources/advertisements/VASTParserTests.swift +++ b/sources/advertisements/VASTParserTests.swift @@ -125,17 +125,24 @@ class VASTParserTests: XCTestCase { XCTAssertEqual(vpaidModel.pixels.collapse.first?.absoluteString, url + "collapse.gif") } - func testParseAdSkipInTime() { + func testParseSkipOffsetInTime() { let vast = getVAST(atPath: "VAST1") guard let model = VASTParser.parseFrom(string: vast) else { return XCTFail("Failed to parse VAST VPAID xml") } guard case let .inline(vpaidModel) = model else { return XCTFail() } - XCTAssertEqual(vpaidModel.skipOffset, .time(3663.123)) + XCTAssertEqual(vpaidModel.skipOffset, .time(3663)) } - func testParseAdSkipInPersentage() { + func testParseSkipOffsetInPersentage() { let vast = getVAST(atPath: "VASTExampleCDATA") guard let model = VASTParser.parseFrom(string: vast) else { return XCTFail("Failed to parse VAST VPAID xml") } guard case let .inline(vpaidModel) = model else { return XCTFail() } XCTAssertEqual(vpaidModel.skipOffset, .percentage(32)) } + + func testParseNotValidSkipOffsetInTime() { + let vast = getVAST(atPath: "VASTVerificationInExtension") + guard let model = VASTParser.parseFrom(string: vast) else { return XCTFail("Failed to parse VAST VPAID xml") } + guard case let .inline(vpaidModel) = model else { return XCTFail() } + XCTAssertEqual(vpaidModel.skipOffset, .none) + } } diff --git a/sources/advertisements/VASTVerificationInExtension.xml b/sources/advertisements/VASTVerificationInExtension.xml index 703a778..69e345c 100644 --- a/sources/advertisements/VASTVerificationInExtension.xml +++ b/sources/advertisements/VASTVerificationInExtension.xml @@ -10,7 +10,7 @@ - +